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.
+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!
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也只看代码。
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
nilfor your enum value no matter what, or how, you set it (to).