Rails ActiveRecord bug
Today I had to make sure a model couldn’t be saved if someone tried to update a certain field.
Reading in the API documentation I found the following:
If a
before_*callback returnsfalse, all the later callbacks and the associated action are cancelled.
So a before_update callback in my model would be the solution. I just had to make sure it would return false in the right cases.
Because of the last three months of test-driven development, I decided to write a test first. And to my surprise I could always save the model, even if my before_update callback would always return false. First I double-checked my test, but it was okay. Time to use yet another great tool in Rails: script/console.
It showed that even though the save method always returned true, it in fact did not save the model. So fortunately no problem with the before_update callback. This meant that there was no way avoiding it anymore… I would take my first dive into the ActiveRecord code.
After quite some time of searching back and forth through a couple of Ruby files, I found the problem:
def create_or_update
if new_record? then create else update end
true
end
And see here, it always returns true instead of the actual result from create or update. Why? Well, probably because there would be a problem in the create method:
def create
self.id = connection.insert(
"INSERT INTO #{self.class.table_name} " +
"(#{quoted_column_names.join(', ')}) " +
"VALUES(#{attributes_with_quotes.values.join(', ')})",
"#{self.class.name} Create",
self.class.primary_key, self.id, self.class.sequence_name
)
@new_record = false
end
This create method returns the value of new_record (which is false), instead of the result of the query (self.id).
I’ve written a simple patch (see ticket #1861), which solves my problems and doesn’t introduce any new problems in my application. But again, it would be good to have a test for ActiveRecord. The problem is that I’m just not well-acquainted with ActiveRecord, so I have no idea where or how to incorporate the test. Any help with this would be greatly appreciated.
MarkusQ on 23 August 2005 at 03:45.
Thanks! You (and Google) answered my question before I’d even clearly formulated it. I was at the ??? stage, but now all is clear.
—MarkusQ