This project is archived and is in readonly mode.

#6621 open
Greg Hazel

explicit callback cancellation instead of implicit based on return value

Reported by Greg Hazel | March 25th, 2011 @ 01:38 AM

I was recently bit by a bug where User records were silently not being saved. Here's a mini example of the sort of error I had:

class User < ActiveRecord::Base

  before_create :foo

  def foo
    if self.age > 30
      self.completed_survey = self.prequalified
    else
      self.completed_survey = true
    end
  end

end

# this one saves
user = User.create(:age => 15, :prequalified => false)
# this one also saves
user = User.create(:age => 35, :prequalified => true)
# this one does not save!
user = User.create(:age => 35, :prequalified => false)

Can you spot the error? The title of the bug gives it away. If the user is over 30 and prequalified is false, foo will accidentally return false and returning false from a before_create callback cancels the save. Also, using User.create instead of User.create! meant no exception was raised, so it went unnoticed for awhile.

This ticket is a proposal to change the interface so that save cancellation is explicit rather than implicit. Something like self.abort_save! could raise a cancel exception. The old interface could be slowly deprecated by warning when false is returned.

If this code was written, would it be accepted?

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages