我正试图让FactoryGirl为我生成一些名字,但序列似乎没有增加.
# 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
规格输出是
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"
解决方法
这样做有点意味着你不能在规范中的任何地方覆盖名称,因为after build钩子将始终运行并覆盖任何名称.
原始示例不起作用的原因是您在定义工厂时调用序列,而不是在工厂运行时调用序列.您可以为每次工厂运行时调用的属性定义提供一个块.这样,您就有机会为每个实例生成一个值,而不是为所有实例生成一个值.这最常用于序列和时间.
您可以使用此代码段修复原始示例:
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
如果可以使用相同的格式生成所有名称,则还可以通过重命名序列来完全省略该值:
sequence :name do |n| "TK42#{n}" end factory :vessel do name vessel_type 'fermenter' volume_scalar 100.0 volume_units 'bbl' end
但是,如果您需要针对不同工厂使用不同的名称格式,则无法使用.