Before Callback Changes in Rails 5
In Rails 4 and below, callbacks like before_validation
always had a gotcha that you had to watch out for:
before_validation :ensure_field_is_false_when_condition
def ensure_field_is_false_when_condition
self.field = false if condition?
end
When condition?
is true
, the assignment happens. However, assignment returns the value that was assigned, so the before_validation
receives the returned value false
. As the docs mention:
If the returning value of a before_validation callback can be evaluated to false, the process will be aborted and Base#save will return false.
This is usually handled by an explicit return
(i.e. nil
does not stop the callback chain):
def ensure_field_is_false_when_condition
self.field = false if condition?
# extraneous return that is not Ruby-ish
return
end
Rails 5 Update
There is a great change to the before_validation
callback behaviour in Rails 5:
If the before_validation callback throws :abort, the process will be aborted and ActiveRecord::Base#save will return false.
This makes halting the callback chain much more transparent and intention revealing:
before_validation :safely_assign_false, :always_halt_validation
def safely_assign_false
self.field = false
end
def always_halt_validation
throw(:abort)
end