I can’t see what I’m missing, but something is obviously not right.
In model:
validates :terms, :acceptance => true, :on => :update
Trying a few options:
>> a = Factory(:blog_agreement)
=> #<BlogAgreement id: 54, terms: false, created_at: "2011-01-20 11:33:03", updated_at: "2011-01-20 11:33:03", accept_code: "fa27698206bb15a6fba41857f12841c363c0e291", user_id: 874>
>> a.terms
=> false
>> a.terms = true
=> true
>> a.save
=> false
>> a.terms = "1"
=> "1"
>> a.save
=> false
>> a.terms = 1
=> 1
>> a.save
=> false
>> a.errors.full_messages
=> ["Terms must be accepted"]
Updated answer..
So it turns out that the problem was having terms as an actual column in the table. In general validates_acceptance_of is used without such a column, in which case it defines an attribute accessor and uses that for its validation.
In order for validates_acceptance_of to work when it maps to a real table column it is necessary to pass the :accept option, like:
The reason for this has to do with typecasting in Active Record. When the named attribute actually exists, AR performs typecasting based on the database column type. In most cases the acceptance column will be defined as a boolean and so
model_object.termswill return true or false.When there’s no such column
attr_accessor :termssimply returns the value passed in to the model object from the params hash which will normally be"1"from a checkbox field.