Why is this Rails inclusion validation failing?

2.1k views Asked by At

Using Rails 3.1.1 by the way. To reproduce this create a new Rails project. Create a new model within this project under the name Example. Create a migration for this model that looks as follows...

class CreateExamples < ActiveRecord::Migration
    def change
        create_table :examples do |t|
            t.integer :status, :null => false
            t.timestamps
        end
    end
end

Have the example model code look as follows...

class Example < ActiveRecord::Base
    VALID_VALUES = [0, 1, 2, 3]

    validates :status, :presence => true, :inclusion => {:in => VALID_VALUES}
end

Now edit the unit test for this model and add the following code to it...

require 'test_helper'

class ExampleTest < ActiveSupport::TestCase
    test "whats going on here" do
        example = Example.new(:status => "string")
        assert !example.save
    end
end

Edit the fixtures file so that it doesn't create any records and then run the unit test with a command such as bundle exec rake test:units. This test should pass as "string" is not a valid status so the example object should return false from the call to save. This is not happening. If you take the 0 out of the VALID_VALUES array then this works. Anyone any idea why this might be the case?

1

There are 1 answers

0
tight On BEST ANSWER

"string" is casted as an integer (as your status column is an integer) before validation

"string".to_i # => 0

You can avoid this by using the numericality validator :

validates :status, :presence => true, :numericality => { :only_integer => true }, :inclusion => {:in => VALID_VALUES}

BTW, you can use #valid? or #invalid? method instead of #save in your test