Factory_bot: Factory for model with `enum` not generating correct data

Created on 14 May 2014  ·  9Comments  ·  Source: thoughtbot/factory_bot

My application has Dossiers which can contain multiple Items:

My setup

# Item class using ActiveRecord::Enum
class Item < ActiveRecord::Base
  enum item_type: %w(file link)
end

# Simplified factory for dossier
FactoryGirl.define do
  factory :dossier do
    sequence(:title) {|n| "Dossier title #{n}" }
    sequence(:description) {|n| "Dossier description #{n}" }
  end
end

# Simplified factory for item
FactoryGirl.define do
  factory :item do
    sequence(:title) {|n| "Item title #{n}" }
    sequence(:description) {|n| "Item description #{n}" }
    item_type { Item.item_types.keys.sample }
  end
end

My tests looks like the following:

feature 'Can view dossier' do
  scenario 'with items' do
    dossier = create :dossier
    3.times do
      item = create(:item)
      dossier.items << item
      # here item's `item_type` is still an integer and the method returns a string; "file" or "link"
      # but when accessing `item` through `dossier`; `item_type` is string of "0" or "1" and the method returns `nil`.
    end
    visit dossier_path(dossier)
  end
end

As described in the comment above the attribute type of item_type changes from integer to string when added to the association.

I'm guessing that it has something to do with the fact that the result of the enum is a string, but the column type is an integer.

I'll try to setup a test case for this and submit a PR.

Most helpful comment

I offer the following breadcrumb in the hope that some other poor soul does not spend an entire day chasing down this ghost, as I just did:

_rake db:test:prepare_

If you did what I did, you had a development database up to date with an enum _and_ a migration, but were running specs against a test database with the enum specified but _no_ column to back it. In this case, Rails/factory_girl will happily infer that the type of the attribute is a string, and the enum logic will happily convert its values to an integer, but they will not be returned as such, and consequently you'll always get nil for your enum value no matter what, or how, you set it (to).

All 9 comments

+1 having the same problem.

@koenpunt @rohitpaulk Just pushed a spec to try this out locally, with what looks to be the same setup - but I'm not able to reproduce the failure. Any additional insight into this would be helpful.

If you check out that branch locally, to run the spec do:

BUNDLE_GEMFILE=gemfiles/4.1.gemfile bundle exec rspec spec/acceptance/enum_spec.rb

@joshuaclayton - You're right, the specs work. Must've been a mistake in my syntax usage. Thanks!

I did setup a similar spec but it passed as well..

And for some reason it now works in my application also.

@koenpunt , @rohitpaulk , @joshuaclayton for me the tests in:

https://github.com/thoughtbot/factory_girl/commit/33d3c063aa1b84fb8f0ef362f8047c58c39d3016

Fail. After I copied them into my Rails project into spec/models/enum_spec.rb
What do I wrong? Can this be because I'm using gem "factory_girl_rails", "~> 4.5.0" there?

Thanks!

Update

I noticed that when I create the factory in the normal console it works! How can this be?

When I run it like this rspec /path/to/enum_spec.rb

I get the follwoing error:

 ActiveRecord enums
     works (FAILED - 1)

  Failures:

    1) ActiveRecord enums works FIXED
        Expected pending 'ActiveRecord::Enum is not defined' to fail. No Error was raised.
       # ./spec/models/enum_spec.rb:6

     Finished in 0.00072 seconds (files took 1.46 seconds to load)
      1 example, 1 failure

    Failed examples:

        rspec ./spec/models/enum_spec.rb:6 # ActiveRecord enums works

I offer the following breadcrumb in the hope that some other poor soul does not spend an entire day chasing down this ghost, as I just did:

_rake db:test:prepare_

If you did what I did, you had a development database up to date with an enum _and_ a migration, but were running specs against a test database with the enum specified but _no_ column to back it. In this case, Rails/factory_girl will happily infer that the type of the attribute is a string, and the enum logic will happily convert its values to an integer, but they will not be returned as such, and consequently you'll always get nil for your enum value no matter what, or how, you set it (to).

@antifun 所说的,test 环境下的 migrate 有问题,可以试着 rollback 然后再 migrate 一次看看。

@antifun 所说的,test 环境下的 migrate 有问题,可以试着 rollback 然后再 migrate 一次看看。

用中文回复美国人?虽然我看comments也只看代码。

Was this page helpful?
0 / 5 - 0 ratings