I realized the importance of reading documentation clearly and with care, when I spent hours debugging this stupid problem.
This is an Active Record callback in action. We are setting a boolean field ‘approved’ to false in the before_create ActiveRecord callback.
1 2 3 4 5 6 7 8 |
class Topic < ActiveRecord::Base before_create :send_to_admin_approval private def send_to_admin_approval self.approved = false end end |
This code is simple, straightforward and looks flawless, until you see a ActiveRecord::RecordNotSaved exception when you try to create a Topic. Our only savior, the errors object also doesn’t give us any information on what went wrong.
Two important things we always forget and aren’t quite obvious are
1. Implicit return values in Ruby. This feature always returns the value of the last executed statement in a method or block.
2. If an ActiveRecord callback returns false, all the later callbacks and the associated action are cancelled.
In our example, the statement ‘self.approved = false’ returns false and since that is the last statement executed in the callback, the callback returns false which cancels the create operation.
So, the best way to set boolean values in an ActiveRecord callback is
1 2 3 4 5 6 7 8 |
class Topic < ActiveRecord::Base before_create :send_to_admin_approval def send_to_admin_approval self.approved = false true # Explicitly return true end end |