12

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" 

FactoryGirlが私の仕様で名前のシーケンスを生成しないのはなぜですか?

4

2 に答える 2

16

これは機能しますが、ビルド後のフックは常に実行され、任意の名前を上書きするため、仕様のどこでも名前をオーバーライドできないことを意味します。

元の例が機能しない理由は、ファクトリが実行されているときではなく、ファクトリが定義されているときにシーケンスを呼び出しているためです。ファクトリが実行されるたびに呼び出される属性定義へのブロックを提供できます。このようにして、すべてのインスタンスに対して1つの値を生成するのではなく、インスタンスごとに値を生成する機会が得られます。これは、シーケンスと時間に最も頻繁に使用されます。

次のスニペットを使用して、元の例を修正できます。

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

ただし、工場ごとに異なる名前形式が必要な場合は機能しません。

于 2012-07-20T04:26:39.210 に答える
2

そして答えは:

require 'factory_girl'

FactoryGirl.define do

  sequence :vessel_name do |n|
    "TK42#{n}"
  end

  factory :vessel do
    vessel_type 'fermenter'
    volume_scalar 100.0
    volume_units 'bbl'
    after :build do |v|
      v.name = FactoryGirl.generate(:vessel_name)
    end
  end
end
于 2012-07-11T22:38:59.823 に答える