Validating Rails boolean fields in RSpec
So I've working on a Rails app recently, using RSpec for Test-Driven Development, and I ran into what I think is a bit of a gotcha, so I thought I'd write up a post on the matter.
One of my models has a Boolean field, and like the other fields, I was trying to validate it using presence validation, and it was failing to be valid even with the initial value I'd set at the beginning of the RSpec file. So, what'd I do? I popped open the Rails Console to get a closer look at what was happening.
I created a new object at the console that matched the values I was using in my test object, including, and this is key, the Boolean field set to false
. Sure enough, with presence: true
validation on that Boolean field, valid?
returned false
. Furthermore, changing the field to true
caused it to become valid.
Now, why is that? To understand why, we must first understand how presence validation works. According to the validations guide, presence validations work by using the blank?
Rails method, which Rails adds to Object
. Next we follow that to the Rails API documentation for Object, where it states under the blank?
method that, "An object is blank if it's false, empty, or a whitespace string." (Emphasis added.)
This tells us that the method blank?
, and thus presence validations, are useless for Boolean fields. So, what to do instead? Enter an answer from StackOverflow. You can use the following line in your model to check the validity of a Boolean field.
validates :field, :inclusion => {:in => [true, false]}
Or if you'd like to use the nice new Ruby 1.9 syntax:
validates :field, inclusion: {in: [true, false]}
One note, however. From my experiments at the Rails console and trying to write tests for proper behavior when non-Boolean values are supplied, if you do supply a non-Boolean value to the field, it will automagically be transformed into either true
or false
according to the rules of what is true
and false
in Ruby.