Ok, the title’s a bit overly dramatic. But i recently stumbled upon a feature of rails callbacks (methods called by before_save, after_create, etc) which meant my code was breaking, in a silent way. After speaking to a few people about it, it seems a lot of people were unaware of this as well. If you don’t want to read me waffling about my voyage of discovery then would you mind just skipping down to my poll about this? I’m trying to get a sense of how many other people didn’t know about this either.
Halfway down the api page documenting callbacks ( http://www.railsbrain.com/api/rails-2.2.2/doc/index.html?a=C00000640&name=Callbacks ) , we read this:
If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_*false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last.
Now, i noticed this only because i encountered what seemed to be a bug in my code. A record wasn’t being saved, and i couldn’t work out why. It wasn’t failing validations. If i tried to do it manually in the console, with the same data, i got this odd situation:
WTF? i thought… after a lot of logging, i managed to work out that it was because i’d added a before_create filter, which set one of the fields to the same as whatever was in a particular field in an associated object, like this:
before_create :set_student_access_to_same_as_music_service</pre> def set_student_access_to_same_as_music_service self.student_access = self.music_service.show_student_access if self.music_service end
So, if the user’s music service’s show_student_access field is false, we set the new user’s student_access to false, as a sensible default value. As a side effect, the method returns false, as that’s the last thing to be evaluated. And because the callback method returned false, the callback chain is halted and the record isn’t saved. But, it’s not failing validations so i don’t get to see why.
Now, i’m not saying this is wrong – it’s in the api after all. I’m just curious as to how many people were also unaware of this – out of the people i’ve spoken to it seems about only half of them knew, which is pretty bad considering it’s a major feature of callbacks, that would be causing unexpected effects all over the place if you weren’t careful about not returning false. So, would you mind answering my poll, below?