Friday, January 16, 2009

Testing Values Returned From ActiveRecord



Be really careful about testing values returned from the db by ActiveRecord. How you fetch it affects the data type. ActiveRecord typecasts the column values returned from the database... sometimes.

This bit me hard today:

If you get a model back from active record e.g. with a MyClazz.find() ActiveRecord::Base will read the dictionary tables and typecast the returned attribute to what you expect. If you use one of the connection class methods, it doesn't do this, it just returns everything as a string.
Comparisons to integer, for example, will FAIL.

Watch this:


# run the console

[chrisa@ibs-chrisa-ux1 lims_m4]$ script/console
Loading development environment (Rails 2.1.1)

# fetch an arbitrary slide

>> s = Slide.find(81247588)
=> #<slide id: 81247588,
slide_group_id: 81246827,
...>

# now, I'm expecting an integer for slide_group_id, so I test it with the == operator:

>> s.slide_group_id == 81246827
=> true

# how nice, principle of least astonishment and all...
# now let's get that same record using the Base.connection method:

>> hash = ActiveRecord::Base.connection.select_one("SELECT * FROM slides WHERE id = 81247588")
=> { "id"=>"81247588",
"slide_group_id"=>"81246827",
...}
>> sgi = hash['slide_group_id']
=> "81246827"

# Whoa. It's a string:

>> sgi == 81246827
=> false
>>

No comments: