Archive for March, 2007

Ruby on Rails is the MacOS to Java/.Net’s Windows

Tuesday, March 20th, 2007

Pierre Igot rants about the user interface for Apple’s Mail.

John Gruber rants about click-through in background windows in OSX.

Both of these (and there are many more if you search the interweb) show the extremely high standards that Apple is held to when it comes to user-interface details. You don’t often see criticisms of Linux or Windows applications that go into such intricate detail:

If you select “Sending…” while Mail is in the process of sending the message, Mail continues to display your list of sent messages, excluding the message currently being sent. In other words, not only does the text label temporarily display a status message instead of the text that should normally describe its contents, but on top of it that temporary message misleads you into thinking that you will be able to see the message that Mail is currently in the process of sending by clicking on it, when actually it does not show you that message.

The reason I mention it is not in some sense of Apple vs Microsoft superiority (I’ve not used Vista or Office 2007 and they are supposed to be OK on the UI front – although I bet you could find a folder caption being used to display a status message if you looked hard enough) but more a sense of Rails vs everything else superiority.

I was talking to another developer today about what I should call a method on one of my objects. My colleague is one of the most talented developers I have ever met but he has never used RoR.

I said “I’m not sure if I should call it account.number_of_events_remaining or account.number_of_remaining_events“. He said either would be fine – “if the name reads right then that’s good enough“. To which I replied “but no matter which one I choose I seem to type the other name“. To Nick this was “operator error” – a problem of typing. To me it was symptomatic of something deeper. The words didn’t feel right. And as we all know if it doesn’t feel right it probably isn’t right. It was a folder caption being misused as a status label.

I could alias the method names – in other words use both. Nick said programmers need consistency. I agreed – aliasing is useful but I think it just adds unnecessary confusion in this case. He suggested I choose one and type it out one hundred times so it becomes imprinted in my brain. This proved to me that the name was wrong – “if i have to force myself to do all of that just to get a property name right then it’s the property that’s at fault – not me“. Plus if we have five developers, with a hundred properties, think how much typing that is before you even write a line of code!

Esoteric discussion by developers with too much time on their hands (I wish)?

In a way, yes; no paying customer will ever see that property (apart from indirectly through the UI).

But, looking deeper, it’s important. Vitally important. Because it’s all about meaning and understanding. When you are looking for the status message do you look to the status bar or your folder list? When you are trying to find out how many events you have left do you have to try different combinations of valid words?

Is it designed so that you “get it” straight away or do you have to rehearse it till you understand?

(In the end, I went with account.remaining_event_allowance)

Filling your database with standing data

Thursday, March 15th, 2007

I’m just adding a new class to my application and it needs a pre-populated list of entries – standing data that will always need to be there. This is pretty easy to set up using migrations and a bit of ERb – and it even works in your test fixtures.

Firstly, create a new migration and define your model. However, do not run the migration yet.
Open your model and add a new class method (I’m using a Colour object for this example):

 def self.build_defaults   build('Red')   build('Green')   build('Blue') end

 private

 def build(name)   Color.create(:name => name) unless Colour.find_by_name(name) end

Simple enough – your build_defaults lists the standing data and build creates it, unless it already exists.

Now go back to your migration file and change it like so:

 def self.up   create_table :colours do | t |     t.column :name, :string   end

   Colour.build_defaults end

Now, when you run the migration it is automatically populated with Red, Green and Blue.

However, there’s a problem. When you run your tests, the database structure is copied but no data. You need fixtures.

Of course, you could just add the fixtures into colours.yml by hand. Easy enough for colours but what if you have something more complex? And if you add new standing data you have two places to make the change – in your model and in your fixtures.

There is an easy answer – fixture files are YAML and therefore can have ruby code (ERb) embedded in them – just like your views.

So edit colours.yml to look like this:

<% Colour.build_defaults %^gt;<% Colour.find(:all).each do | colour | %> <%= "#{colour.name.gsub(' ', '_')}" %>:   id: <%= colour.id %>   name: <%= colour.name %><% end %>

The first line builds your defaults into the test database.
The next line goes through all colours in the database and for each one generates your fixtures YAML. Firstly the fixture name – this is the colour name (with underscores instead of spaces). And next (watch the indentation) the id and name fields.

Once more, Rails makes it easy.

Deploying to a Staging Server with Capistrano

Thursday, March 15th, 2007

Capistrano is one of my favourite Rails features. It’s vital to “agile” development – there’s no point running through your iterations, making fast, small changes, if you can’t easily get them into the hands of the (hopefully) paying public. (It’s also a major reason I’m not too interested in deploying on IIS any more).

However, one of the things I have found is that sometimes you get stuff that runs fine on your local boxes but fails on your server (I had a weird one where Bluecloth worked fine here but not there – despite freezing all my Gems and Rails itself).

So I wanted to set up an intermediate deployment on my server.

A quick hunt found Mike Burn’s article which I then adapted for my own purposes.

Firstly – created a new subdomain and database on my server – and a folder for deploying to.

Then I added a new environment file – /config/environments/staging.rb – this was a copy of development.rb but with code caching turned on.

Next, I set up a new database configuration in /config/database.yml – staging: that points to my newly created staging database.

To get Capistrano to deploy correctly, I amended /config/deploy.rb like so:

if stage == "production" set :deploy_to, "/home/user/myapp_live"else set :deploy_to, "/home/user/myapp_staging"end

I also needed to adapt things after the code had been copied, so the following was added to the end of deploy.rb:

desc "After updating the code, back up the database and migrate"task :after_update_code do run "/home/user/mysql/backup.sh"  # if this is a staging deployment, switch the environment to staging, not production  if stage == "staging"   # switch to the staging environment   run "sed -i 's/\"production\"/\"staging\"/' #{release_path}/config/environment.rb"   # migrate the database   run "cd #{release_path} && rake RAILS_ENV=staging db:migrate" else   # migrate the database   run "cd #{release_path} && rake RAILS_ENV=production db:migrate" endend

Basically, I did not trust the deploy_with_migrations task to work the way I wanted it to (I kept noticing rake RAILS_ENV=production db:migrate appearing in the log).

So instead I back up my database manually using a script and then – if I’m in production mode I just migrate the database (explicitly setting the Rails Environment). However, if I’m in staging mode then I use sed to change my environment settings (so that the line ENV["RAILS_ENV"] ||= "production" becomes ENV["RAILS_ENV"] ||= "staging") and then migrate the database (explicitly setting the Rails Environment).

One final step – I created two shell scripts – deploy and deploy_to_production that look like this:

# deploy#! /bin/shcap -S stage=staging deploy# deploy_to_production#! /bin/shcap -S stage=production deploy

These call Capistrano’s deploy task, setting an internal variable stage to “staging” or “production” respectively.

Further Enhancements – I’m going to change deploy.rb so that it uses different Subversion Urls for staging and production – so staging pulls from http://mysvn/myapp/staging and production pulls from http://mysvn/myapp/live.

It’s great when you’re straight … yeah!

Friday, March 9th, 2007

The man is a hero. The fact that he is alive at all, let alone created some of my favourite records makes him so.

My friend got me Bez’s autograph. He signed a book of matches – “all the Bez“.

Bez taught me how to dance. As my twelve-year old will testify.

It’s a special day …

Friday, March 2nd, 2007

… when your application gets its first paying customer (even though it’s still in alpha).