Friday, May 25, 2007

Currency formatting stuck in Rails' Views

I've been re-doing the Depot application tutorial from the excellent Agile Web Development with Rails book as I've updated it for the latest version of Rails in order to get a better handle on REST and other changes in Rails 1.2.3. I'm mostly doing it on the train in the morning and evening.

Anyway, as I go I'm challenging the approach given in the book to validate my own Rails/OO design knowledge. One area where I thought I could see a better way of doing things was with the formatting of the prices in the store view. Previously I had used sprintf() to give me a display_price facade attribute in the Product model that I could use for pretty (i.e. currency specific) versions of prices.

The number_to_currency helper method seemed to offer a great way of doing the currency formatting, especially given the helpful options it has for setting all sorts of specific details like currency symbol, separators for thousands etc. The tutorial showed it being added into the Store view, which is nice, but potentially could leave me with a whole lot of places to make changes if I wanted to internationalise the application (although the elements could be stored in constants). However when I plugged it into my Product model it threw a nasty error:
undefined method 'number_to_currency'
It turns out that this helper method is part of ActionView and so can't be used in models or controllers (the documentation I link to above has comments about that under it). The workaround is to use sprintf() within models or controllers. At least the database column is now automatically detected as a BigDecimal rather than a Float so my previous hack is no longer required.

So is there a problem with this? On the one hand, I can see that number_to_currency is all about creating a string representation of a number, and thus sits squarely within the world of views. On the other hand the DRY principle militates that we should have a single authoritative source of this information, without creating larger issues. In theory this means the model layer, although it is unclear whether you would restrict yourself to the Rails models or the underlying database objects.

My rule of thumb is to KISS it and use the Rails model when you know everything you write will be in Rails. If you expected to have non-Rails applications accessing the data (e.g. legacy .NET or Java code) then I would look at creating a view (less flexible currency styling) or stored procedure to act as the database source object for my Rails and .NET models.

No comments:

Post a Comment