Why does false invalidate validates_presence_of?

Ruby on-RailsUnit TestingValidation

Ruby on-Rails Problem Overview


Ok steps to reproduce this:

prompt> rails test_app
prompt> cd test_app
prompt> script/generate model event_service published:boolean

then go into the migration and add not null and default published to false:

class CreateEventServices < ActiveRecord::Migration
  def self.up
    create_table :event_services do |t|
      t.boolean :published, :null => false, :default => false
      t.timestamps
    end
  end

  def self.down
    drop_table :event_services
  end
end

now migrate your changes and run your tests:

prompt>rake db:migrate
prompt>rake

You should get no errors at this time. Now edit the model so that you validate_presence_of published:

class EventService < ActiveRecord::Base
  validates_presence_of :published
end

Now edit the unit test event_service_test.rb:

require 'test_helper'

class EventServiceTest < ActiveSupport::TestCase
  test "the truth" do
    e = EventService.new
    e.published = false
    assert e.valid?
  end
end

and run rake:

prompt>rake

You will get an error in the test. Now set e.published to true and rerun the test. IT WORKS! I think this probably has something to do with the field being boolean but I can't figure it out. Is this a bug in rails? or am I doing something wrong?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

See the API docs...

> If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, :in => [true, false].

Solution 2 - Ruby on-Rails

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

no longer works for some versions after 1.3.0 of the shoulda matchers when you are testing that only Boolean values are accepted by your model.

Instead, you should do something like this:

it { should allow_value(true).for(:your_field) }  
it { should allow_value(false).for(:your_field) }
it { should_not allow_value(nil).for(:your_field) }

You can see the discussion here.

There was a partial fix for this that now warns if you are trying to do this here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaaronaView Question on Stackoverflow
Solution 1 - Ruby on-RailsTony FontenotView Answer on Stackoverflow
Solution 2 - Ruby on-RailsFaridView Answer on Stackoverflow