Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
669 views
in Technique[技术] by (71.8m points)

ruby on rails 3 - Factory Girl sequences not incrementing

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...