Mr eel

Web Development

Sass & Haml - A Sweet Romance Begins

If you’re just starting out using Sass, you can make things easier on yourself by having it automatically compile the stylesheets with every request. This tip applies to both Rails and Merb. Just add the following bit of code to your development.rb file.


Sass::Plugin.options[:always_update] = true

P.S. After being dubious for some time, I’ve now begun my romance with Haml and Sass. It’s sweet indeed. Terse, auto-formatting, variables. Oh my. Delicious.

Posted on January 20th, 2008 | There are 2 comments

More New Merb (0.5 is out now)

Just a quick heads-up. Merb has moved pretty quickly over the last few weeks, with lots of nice additions, code refactoring and general polish.

Now, Merb 0.5 is out. You can install it via RubyGems. Ezra has release notes on his blog.

Well done to all the devs! Merb just keeps looking better and better as it goes along. Yay!

Posted on January 10th, 2008 | There are 0 comments

CSS - Image Replacement Hot Melon Jam Fu

There are loads of image replacement techniques and I think I’ve experimented with most of them. More recently I’ve hit on a set of rules that are pretty bulletproof and thankfully don’t require any kind of hacks.

It hinges on using the letter-spacing rule — big ups to Beej for putting me onto that one. The basic idea is that you set the letter spacing to a negative value. The text essentially collapses and disappears. The best part is that the element doesn’t otherwise change. It still keeps it’s width, height and positioning. You can now freely change the height or width without having to make hacks to accommodate Internet Explorer’s horrible rendering engine.


.imageReplacement {
  background:left top no-repeat url(/images/heading.gif);
  letter-spacing:-1000em;
  text-indent:-1000em;
  width:250px;
  height:70px;
}

There are two quirks to look out for here. Firstly the letter spacing has to be -1000em. After experimentation, other more patient people have discovered that it is the value that works reliably across most browsers. Secondly, the text-indent is there to hide the text in Safari and early version of IE, where the letter-spacing rule does not correctly apply. It forces the text to sit outside the container, so it disappears. Using both text-indent and letter-spacing together means you’ll hide the text reliably in most browsers.

I’m not sure it’s the Holy Grail of image replacement, but it’s pretty good!

P.S. .imageReplacement is a horrible class name. I only use it as an example. I prefer to use class names that refer to what the element is and what it does, rather than how it looks. Much easier to modify later on.

Posted on November 30th, 2007 | There are 2 comments

Rails - acts_as_tree Select Helper

Do you have a model with acts_as_tree? At some point you probably might want to generate a select with a representation of your tree — say categories and sub-categories for blog posts or something. I’ve seen some slightly nasty ways of doing this, so I thought I might try my hand at something cleaner.

Firstly, the most efficient way of building the options for the select is via recursion. Secondly, you shouldn’t try to do it with one method, otherwise you’ll end up checking conditions repeatedly — Is this the top level? Do I have to write out the select open or select close? — when you really don’t need to.

So I’ve split my helper into two methods. One to generate the select tag and another for the options. The method for the options recurses, going through each level in the hierarchy.


def select_for_tree(model, name, entries, options = {})
  # Grab the current value of the specified attribute
  current = instance_variable_get("@#{model}").send(name)
  # Build the option tags
  option_tags = options_for_tree(entries, current, 0)
  # Check to see if we need to include a blank entry at the top
  option_tags.insert(0, content_tag(:option)) if options[:include_blank]
  # Build the select tag
  select_tag("#{model}[#{name}]", option_tags, :id => "#{model}_#{name}")
end

def options_for_tree(entries, current, level)
  options = ''
  entries.each do |entry|
    attrs = {:value => entry.id}
    attrs[:selected] = 'selected' if entry.id == current
    options < < content_tag(:option, ("- " * level) + entry.name, attrs)
    # This is the bit that does the recursion.
    options << options_for_tree(entry.children, current, level + 1) unless entry.children.empty?
  end
  options
end

Not particularly clever, but it was interesting trying to get something reasonably simple and clean.

Posted on November 27th, 2007 | There are 3 comments

Just What The Bloody Hell is a Merb?

I’ve posted about Merb a few times, but I noticed I haven’t actually given anything like an introduction to the framework, which might be useful considering it’s not too well-known. Well, I’m not gonna do that since other nicer, better-spoken people have done it already. So here is a few links to get you started.

Merb

The official site, which has got a good overview of the framework and installations. I recommend starting with the Why Merb? page, which will hopefully convince you to give it a serious look. After that, look at the Features page.

Merb & Datamapper: Getting Rolling

A quick introduction to installing Merb and DataMapper. It should be enough to get you started coding. A slight aside; DataMapper is a really awesome ORM, my preferred choice when using Merb.

Wycats’ Introduction to Plugins

Plugins in Merb are implemented as Gems, not a custom format. The benefits for doing this are manifold. Here Wycats gives a good overview of both creating and using Merb plugins.

Wycats on the Mailer

Merb’s mailer is a very nice, well thought out bit of work.

Hassox - The Great Merb Speedup

Merb is pretty fast. The code in trunk is even faster. There has been loads of good work in the last month or so, which has seen Merb speed up many times over. Hassox has got some rather tasty benchmarks :)

Hassox - The Provides API

Previously Merb had a respond_to API similar to that in Rails. This has since been replaced with a cleaner alternative; the provides declaration.

Posted on November 22nd, 2007 | There are 0 comments

Ye Newbyes Gyde to Routing in Merb

The part of the Merb I’ve found most interesting lately is the routing. A fair number of people will be familiar with the routing in Rails. Have you ever considered how useful it is? For simple cases it does it’s job with no fuss, but if you want to get clever, most of the time you’re just out of luck.

Consider this; how do you route a request based on the subdomain? Can’t. How about based on the protocol? Nope. The port number? Naah. How about using a regular expression to analyze a URL? Shit out of luck my friends.

Merb’s routing holds the answers! It can do all of that with a much nicer syntax in it’s DSL. So, for the sake of illustration I might run through a few examples from an application I’m currently working on — I’m no expert, so these will just be simple ones.

First something real simple. Sending requests on the root url to a particular controller and action. First we match() the url. Then we specify the controller and action we want to send it to. OK… so not that clever.


r.match('/').to(:controller => 'home', :action => 'index')

Another simple one to demonstrate the use of place holders in the match. Any parts of the URL that appear where you specify a place holder will then be available in the routing.


r.match('/:controller/:action').
  to(:controller => ':controller', :action => ':action')

Just to demonstrate, you could have a weird URL scheme like this:


r.match('/:id/:controller').
  to(:controller => ':controller', :action => 'show', :id => ':id')

Now time to show some awesomeness. You can send requests to controllers that live in a particular module based on the subdomain.


r.match('/:controller/:action', :subdomain => ':subdomain').
  to(:controller => ':subdomain/:controller', :action => ':action')

This would be perfect for redirecting the requests via an admin subdomain. So requests to admin.domain.com/users would get sent to the controller/action Admin::Users#index. Nice!

I should also point out that you can also easily turn each one of these route declarations into a named route. Like so:


r.match('/login').to(:controller => 'users', :action => 'login').name(:login)

You just call #name at the end of the route declaration and pass in a symbol which will be the name you can then use in your #url calls inside controllers and views.

Ok, one last cool thing. You can match to a segment of a URL, then define a bunch of sub-matches. This is done by passing a block to the match method.


r.match('/admin') do |admin|
  admin.match("/:controller").
    to(:controller => "admin/:controller", :action => 'index')
  admin.match("/:controller/:id").
    to(:controller => "admin/:controller", :action => ":show", :id => ':id')
  %w(edit delete).each do |action|
    admin.match("/:controller/:id/#{action}").
      to(:controller => "admin/:controller", :id => ":id", :action => action)
  end
end

So what I’ve done here is match against /admin then we go onto our sub-matches. First the controllers index action. Then with an id, we map to the show action. Finally we map to the new and delete actions. This isn’t a real world example, since we’re only crudely emulating RESTful routing, but it shows how flexible you can be with matching parts of a url.

In my next Merb(ivorian) post I’ll go into a little more detail about the resources route declarations and doing some more clever stuff with ports and sub-domains. OH YEA.

Posted on November 20th, 2007 | There are 1 comment

New Site, New Site I Even Love Saying the Word Site

So, I got a bit bored and stuff. For no particular reason, I thought I might have a go at redoing the design for this blog. I like what I’ve ended up with. It’s well serious.

It was an experiment with trying to get the markup as minimal as possible. I’ve only used three divs, the rest is all nice semantic stuff. The next step is to actually get it to validate as XHTML 1.1. This might be a bit tricky since every link needs to have a title attribute — eeek! — and the source needs to start with the XML prolog. The last is a tricky one. Many many browsers and servers just blow up when trying to serve an XML doc using the text/html mime-type — which is derived from the extension.

Validation seems positively quiotic sometimes. I shouldn’t say it less the standards-types beat me up, but I really don’t see the point of many of the requirements in the spec. So rather than fussing about it, I figure I’ll just work to keep things neat, tidy and consistent.

That will have to do.

Posted on November 20th, 2007 | There are 2 comments

Fixtures with Datamapper and Merb

If you’re to be using Datamapper with Merb, you might be wondering how to get your test fixtures into your test database.

Thankfully it’s pretty simple. For those of you using Rspec, just stick this bit of code in you spec/spec_helper.rb


# Make sure the schema is in sync
DataMapper::Base.auto_migrate!

def fixtures(*files)
  files.each do |name|
    klass = Kernel::const_get(Inflector.classify(Inflector.singularize(name)))
    entries = YAML::load_file(File.dirname(__FILE__) + "/fixtures/#{name}.yaml")
    entries.each do |name, entry|
      klass::create(entry)
    end
  end
end

If you haven’t seen the auto_migrate! in DataMapper before, be aware that it destroys and recreates your database schema. I like to add it to my spec_helper so that the test DB is in sync with development, without me having to run a rake task.

This method assumes your fixtures are in the spec/fixtures directory and use the yaml extension. If you’re using .yml instead, you’ll need to change the third line in the fixtures method.

Now just call fixture inside your describe blocks.


describe "make sure the yowie is real" do
  fixtures :yowies
end

Keep in mind this will likely be a bit slow if you have loads and loads of fixtures, but for simple cases it works nice!

Posted on November 12th, 2007 | There are 0 comments

Pffffft, I.T. Revolution in Australia eh?

I’m quite seriously considering leaving programming and web development. Or at least getting out of the field for a little while. Perhaps go over-seas.

The I.T. industry in Australia sucks.

As someone commented to me recently, so much of it is just selling stuff made elsewhere and as far as software engineering goes that usually just means deployment. There is very little original thought or innovation here. Perhaps in pockets, but by and large it’s all crap.

Being an employee in the industry is arse. Your passion for technology and good craft will get exploited, but too few employers feed that passion. You will be expected to understand complex systems, be able to work autonomously — yet put up with management interference at arbitrary points, at the drop of a hat learn skills outside your original job description and do all this to stupid artificial deadlines.

You will not get paid properly to do this.

Yes, I’m feeling a wee bit bitter. Yes, it’ll probably pass. I’m not usually given to having a public whinge about things like this, but I’m feeling particularly grumpy at the moment.

I guess after a fairly good, long run in the industry I’ve just about hit ‘completely dis-illusioned’.

Bugger :/

EDIT: Alright, I’ve kinda gotten over it. But my criticisms are still valid I believe.

Posted on September 24th, 2007 | There are 0 comments

Soz, But Rails is Slow

The level of performance Rails delivers out of box is almost laughable compared to even archaic frameworks like ASP Classic. 120 requests-per-second for a cacheless ASP Classic application is pretty straight-forward, but doing the same with Rails would be quite a feat without a comparatively insane amount of resources available.

This quote courtesy of Sam Smoot. He’s absolutely right. I have discovered this first hand. Ruby on Rails is a sloooooooow motherbitch. I love it like an ugly child. It’s special, but it still annoys me.

I’ve heard the arguments about scaling. My favourite is that hardware is cheaper than developer time, so just throw some new servers at the application. That only works if you’ve actually got the money. Besides it’s an inelegant, brute-force approach. Yes, you will need heavy hardware to deal with high traffic regardless of the framework, but Rails needs that hardware a lot earlier than most.

There are so many points in Rails that should be changed to improve performance. For example an update through ActiveRecord actually updates every field in the DB, regardless if it has been changed. That’s so obviously dumb. But as far as I know there are no plans to change it.

Luckily there are other alternatives, but that’s for another post :)

Posted on August 15th, 2007 | There are 0 comments

All contents © 2005—2007 Luke Matthew Sutton