problem with passing booleans to update_attributes
Asked Answered
N

3

30

I've got the following Model:

class GuestCatering < ActiveRecord::Base

  # Validation
  validates :name, :presence => true
  validates :order_number, :presence => true
  validates :orderable, :presence => true

end

But when I'll try to update an existing GuestCatering with the following code:

guest_catering.update_attributes(:orderable => false)

The guest catering variable is a valid GuestCatering object. The guest_catering object has errors after the update, like that:

<{[:orderable, ["can't be blank"]]=>nil}>

But when i pass a orderable => true, everything is fine and no errors.

What's wrong here, why can't i set orderable to false?

Nucleoside answered 7/3, 2011 at 11:32 Comment(1)
Try this: guest_catering.update_attributes(:orderable => 0)Pregnant
P
43

Your model is actually behaving exactly as you told it to, through your use of validates :orderable, :presence => true

There's little point validating the presence of a boolean flag - it's going to be true, nil or false - and in Ruby world, nil and false have the same semantic value when it comes to boolean logic.

Internally, validates :presence relies on the value of the attribute being checked to return false when blank? is called. And, in Rails (with ActiveSupport), false.blank? evaluates as true - which means that your field is failing the validation.

Simply remove that validation and everything will work as expected.

Poppycock answered 7/3, 2011 at 11:59 Comment(3)
So I can't validate a boolean flag?Nucleoside
How would you validate it? It's either on or off. If you need it to be true (such as agreeing to terms), then you could use a validation to enforce it. In your case, it doesn't appear to be required.Poppycock
Thanks this helped me out a lot i was in a similar predicamentSipes
C
21

Like Dan Cheail already said in his answer, a nil and false boolean is semantically the same thing.

But, if you really need to validate it (not allowing nil), you can always do :

validates_inclusion_of :orderable, :in => [true, false]

Craquelure answered 6/12, 2012 at 11:8 Comment(1)
If your database column for your boolean is NOT NULL, this is the correct answer as this will validate the field before attempting to write the record. The other answer will allow the validation to pass with nil, but .save will error on the column restriction.Dictation
E
-2

Instead of validates :presence => :true, you should write your migrations with the default value like this:

t.boolean :orderable, :default => 0

I assume your default value should be false. If true, use 1 as default. Then it will set the default value in database. So, you can omit the validation check.

The reason you cannot use validates :presence is answered by @dan. Presence means not blank and Rails use .blank? function for this and false.blank? is true

Elastin answered 7/3, 2011 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.