3

In my rails (4.2.1) app, I have a Post model with an integer field foo. While creating a post, I passed a string to the integer field. I expected an error, but the record got created with foo set to nil. Why don't I get an error?

# migration
class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :name
      t.integer :foo

      t.timestamps null: false
    end
  end
end

# post creation, no error ???
Post.create!(name: 'a post', foo: 'a_string')

# post has nil value in foo
Post.first
#=> Post id: 1, name: "a post", foo: nil, ...

Actually, I wanted to write a failing test for the Post, and then I would change foo to be an enum to make the test pass. I was surprised that the test did not raise an error.

1 Answer 1

6

It's a "feature" of the db. Rails at this point doesn't know about the type of the attribute. If you want it to only accept integers, you can use validates_numericality_of :foo.

If you want your test to fail while it's not an enum, you could do something like

expect { subject.foo = 'invalid value' }.to raise_exception(ArgumentError)

that way it will fail as long as it's not an enum.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I don't want it to only accept integers. I want to write a failing test (TDD) to make the field an enum. I could check that the field after creation is the expected value, but is there a better way?
Not sure if I understand correctly, but if it should be an enum, you can use the ActiveRecord::Enum feature. That way it won't accept any invalid numeric values but will still be settable from strings and ordinals.
Yes, I want to use the Enum feature - but how do I write a test that fails first, and then add the enum line in the model to make it pass?
@Anand I understood now, added a sentence about that to my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.