I'm trying to get FactoryGirl to generate some names for me, but the sequence doesn't seem to increment.
# spec/factories/vessel.rb
require 'factory_girl'
FactoryGirl.define do
sequence :vessel_name do |n|
"TK42#{n}"
end
factory :vessel do
name FactoryGirl.generate(:vessel_name)
vessel_type 'fermenter'
volume_scalar 100.0
volume_units 'bbl'
end
end
# spec/models/vessel_spec.rb
require 'spec_helper'
describe Vessel do
context 'working in the factory' do
it 'makes a valid vessel' do
vessel = FactoryGirl.create(:vessel)
vessel.should be_valid, "Invalid vessel #{vessel.valid? || vessel.errors.messages.inspect}"
end
it 'makes another valid vessel' do
vessel = FactoryGirl.create(:vessel)
vessel.should be_valid, "Invalid vessel #{vessel.valid? || vessel.errors.messages.inspect}"
end
end
end
The spec output is
Vessel
working in the factory
makes a valid vessel
makes another valid vessel (FAILED - 1)
Failures:
1) Vessel working in the factory makes another valid vessel
Failure/Error: vessel = FactoryGirl.create(:vessel)
ActiveRecord::RecordInvalid:
Validation failed: Name has already been taken
# ./spec/models/vessel_spec.rb:13:in `block (3 levels) in <top (required)>'
# app/models/vessel.rb
class Vessel < ActiveRecord::Base
attr_accessible :name, :vessel_type, :volume_scalar, :volume_units
validates :name, :presence => true, :uniqueness => true
end
0 HAL:0 work/nrb-brewery-management % bundle show factory_girl_rails rspec
/home/brundage/.rvm/gems/ruby-1.9.3-p0/gems/factory_girl_rails-3.5.0
/home/brundage/.rvm/gems/ruby-1.9.3-p0/gems/rspec-2.11.0
0 HAL:0 work/nrb-brewery-management % rails c test
Loading test environment (Rails 3.2.6)
1.9.3p0 :001 > FactoryGirl.generate :vessel_name
=> "TK422"
1.9.3p0 :002 > FactoryGirl.generate :vessel_name
=> "TK423"
1.9.3p0 :003 > FactoryGirl.generate :vessel_name
=> "TK424"
1.9.3p0 :004 > FactoryGirl.generate :vessel_name
=> "TK425"
Why doesn't FactoryGirl generate a sequence of names in my spec?
That works, bit it will mean that you can't override the name anywhere in the specs, because the after build hook will always run and overwrite any name.
The reason your original example doesn't work is that you're invoking the sequence when the factory is defined, rather than when the factory is run. You can provide a block to attribute definitions which will be invoked every time the factory runs. This way, you get a chance to generate a value for each instance, rather than generating one value for all instances. This is most frequently used for sequences and times.
You can fix your original example with this snippet:
sequence :vessel_name do |n|
"TK42#{n}"
end
factory :vessel do
name { generate(:vessel_name) }
vessel_type 'fermenter'
volume_scalar 100.0
volume_units 'bbl'
end
If all names can be generated with the same format, you could also leave out the value entirely by renaming your sequence:
sequence :name do |n|
"TK42#{n}"
end
factory :vessel do
name
vessel_type 'fermenter'
volume_scalar 100.0
volume_units 'bbl'
end
However, that won't work if you need different name formats for different factories.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With