Is there any benefit in having validations for boolean fields of models?
I had a validation for ensuring the presence of a boolean field
validates :boolean_attribute, presence: true
It failed when boolean_attribute was false. I googled around and found these SO questions relating to the issue.
Rails database defaults and model validation for Boolean fields
Rails validates_presence not validating on Boolean?
Then added this validation instead
validates :field, :inclusion => {:in => [true, false]}
This made me think. Do I need any validations for boolean fields at all? Its value will always be true or false or nil right? Even if someone maliciously try to change it to say, a number, wouldn't the type take care of it? Or is there some safety the above inclusion validation provides?
parseBoolean(String s) − This method accepts a String variable and returns boolean. If the given string value is "true" (irrespective of its case) this method returns true else, if it is null or, false or, any other value it returns false.
Validation in Spring Boot is done mainly by using Hibernate Validator — an implementation of Java Bean Validation using annotation based constraints. But while Hibernate provides a powerful set of constraint violations checkers out of the box, we'll need to put some effort into handling the exceptions it throws.
The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.
Whether or not you should validate a boolean attribute for inclusion in [ true, false ]
depends entirely on your use case.
You've correctly identified that, in the absence of validation of other code, a boolean field in Rails will always be (after type coercion) true
, false
, or nil
. Rails won't coerce nil
to false
. If you set a model's boolean attribute to nil
and save it, the attribute will be nil
, not false
, when you fetch the it from the database later.
You can think of nil
as a "third state" for a boolean field. Consider a simple survey app that lets users save an unfinished survey to complete later. Suppose a user saves an incomplete survey with the question "Do you eat meat?" unanswered. You don't want to store false
in the database because that would indicate that the user answered "no." When the user comes back to finish the survey you want that question to still be unanswered, so you want to store nil
in the database.
In cases like the above, it's appropriate (and necessary) not to validate for inclusion in [ true, false ]
.
However, as a rule of thumb I would say that in all other cases—i.e. in any case where you don't have a specific need for nil
values—you should validate boolean fields for inclusion in [ true, false ]
.
Of course, if you do allow nil
you'll need to be careful because, as you know, nil
is a falsey value in Ruby. You'll have to explicitly check for "nilness" in places where you might otherwise rely on a value's truthiness or falsiness. That is, instead of this:
if !is_meat_eater
unanswered_questions << :is_meat_eater
end
...which will not behave as intended if is_meat_eater
is false
, you'll need to explicitly check for nil
:
if is_meat_eater.nil?
unanswered_questions << :is_meat_eater
end
You don't need to validate a boolean
field, if it's not true it's false.
Just set a "default" in your db so that the bool is always going to have a certain value no matter what:
#db/migrate/add_boolean_column_______.rb
class AddBooleanColumn < ActiveRecord::Migration
def change
change_table :table do |t|
t.boolean :field, default: false
end
end
end
This way, I wouldn't even include any validations. The system will ensure you're either setting it as true or false - which is up to you as the developer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With