Well, it wasn't, once I invested in Programming Ruby and Agile Web Development with Rails. Those two books helped me considerably, especially the follow-on tutorials in the Rails specific one. Without those I would have been left floundering.
However, there were two problems that neither book really helped me with (although the first one was properly shown in the Programming Ruby book, it just didn't bother to point out the weirdness of it).
Elsif
You might not have realised it, but that heading above is missing an "e" (and a space, but most programming languages ignore that). Unlike any other language I have learnt, Ruby's If ... Elseif ... End construct spells the "Elseif" without the second "e", as in "Elsif". Perhaps it was because Matz is Japanese, but this really threw me - I even ignored the way the Ruby book showed me it was.Decimals
Rails' ActiveRecord is very nice for doing lots of hard work for you. Thank you very much David Heinemeier Hansson. Unfortunately it maps decimal database columns to float variables ... which if you have ever tried using floating numbers in financial calculations you would know means major problems!Frankly this is a show-stopper for me. I can't imagine ever doing something real with Rails that would not involve dollars, and I certainly do not want nasty rounding errors creeping in because there are floats mapped to my decimal table columns. It turns out that the solution in Ruby is to use the BigDecimal data type. It took a little while to find the API documentation for this datatype, but eventually I did.
That didn't help me work out how to implement it. The Rails community is full of talk about modifying ActiveRecord to do the job properly - but it turns out that ends up involving a lot of database-specific code, and whilst ProgresSQL and SQL Server have been done, good old MySQL is left wanting, and that is what I am using to play around with. There is a little blurb in the book about overriding the accessor/mutator attributes for a model (don't worry if that makes no sense to you, it didn't to me either until about 8 hours into the tutorial). The online API documentation for ActiveRecord seems to hint that the _before_type_cast accessor could help here.
After too much mucking about, I finally got an answer that is elegant and works very nicely. I even have some sample code for those other newbies following the Rails tutorials. At the beginning of our Product model we need to add a couple of lines:
# modified this to get the price as a decimal
require "bigdecimal"
require "bigdecimal/util.rb"
Then later, we can override the default price accessor/mutator with a simple call to BigDecimal:
def price
# we want to make Price a BigDecimal, the format
# will look weird if we don't do anything to it
# but we are using sprintf() in our fmt_currency
# method, which handles this nicely
BigDecimal(price_before_type_cast, 2)
end
As I've noted, the main problem with BigDecimal is that the native display of it is ugly. A value of 20.00 is displayed as 0.2E2, which is nasty. Fortunately the formatting seems to work out in text fields OK, and we end up formatting price everywhere we show it as a label so that it shows with dollar signs. The formatting function sprintf() has no problem with BigDecimal so that works fine!
So far (and I have all of the cart code working) this does not seem to lead to any issues with the Depot tutorial, and it gives an elegant solution (provided you are willing to create a formatting method for displaying these numbers wherever they are outside form fields).
[EDIT: The year-old enhancement request relating to the decimal issue is an interesting read.]
Submit to Reddit