FactoryGirl循环依赖和validation

我是FactoryGirl的新手,在Ruby中,我正在尝试编写一些rspec但是我遇到了一些循环依赖的麻烦。 我搜索并尝试了几个东西,最后一个产生了无限循环,我不得不关闭我的WM。 (proc 100%)

车型/投票

class Vote < ActiveRecord::Base has_many :vote_options 

车型/ vote_option

 class VoteOption < ActiveRecord::Base belongs_to :vote accepts_nested_attributes_for :vote_options, reject_if: :all_blank 

规格/型号/ vote_spec

 describe Vote do describe 'should return the good label' do let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } it "should not be visible" do nobody.intercom_custom_data[:visibility].should == I18n.t("votes.new.visibility_none") end end end 

规格/工厂。

 factory :vote do team question 'Question?' question_type 0 # Avoid validation because of the circular dependency. # https://stackoverflow.com/questions/9322353/factory-girl-create-that-bypasses-my-model-validation after(:build) do |vote| vote.vote_options < false) end end factory :vote_allowed do user vote allowed 1 end factory :vote_casted do vote_allowed vote_options end factory :vote_options do vote title 'default option' end 

这是执行无限循环的代码。 我猜它由于循环依赖而无限制地创建了投票和投票选项。

所以,我得到了一个投票,其中有很多vote_options(用户选择),每个vote_options包含其父ID。 如果字段为空,则validation拒绝创建,我们在此代码中没有问题来保存新的投票/ vote_options,因为所有内容都在同一事务中完成。

但是,使用rspec,我无法同时创建投票和vote_options行相互依赖。 (或者我不知道怎么做)

所以,我试图避免这样的validation:

 after(:create) do |vote| VoteOption.create(vote_id: vote.id) vote.save!(:validate => false) end 

但是我收到了一个错误:

 Failure/Error: let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } ActiveRecord::RecordInvalid: Validation failed: Vote options can't be blank 

我之前尝试使用after_create而不是after(:create) ,但我的FactoryGirl在4.3中,所以after_create不再存在。 我在https://stackoverflow.com/questions/15003968/undefined-method-after-create-with-factorygirl上找到了一个关于“如何在> 3.3中使用after_create”的教程,但它对我不起作用,我不应该得到“投票选项不能为空”…所以我看看上一个链接中链接的文档,我试图添加规范/工厂

 FactoryGirl.define do after(:create) {|instance| instance.create } 

但我真的不明白我应该做什么,我不明白问题出在哪里。 任何的想法?

编辑#1:

 factory :vote do team question 'Question?' question_type 0 association :vote_options, factory: :vote_options # tried with :create and :build after(:create) do |vote, evaluator| create_list(:vote_options, 1, vote: vote) end end 

你有没有按照文件的协会章节做过?

 ignore do vote_options_count = 1 end after(:build) do | vote, evaluator | create_list( :vote_option, evaluator.vote_options_count, vote: vote ) end 

之后应该允许访问如下:

 create(:vote).vote_options.length # 0 create(:vote, vote_options_count: 15).vote_options.length # 15 

注意vote_option工厂必须定义为单个,而不是复数。

我确实喜欢这个:

规格/工厂。

 factory :vote_option do vote title 'default option' end factory :vote do team question 'Question?' question_type 0 vote_options_attributes {[{ title: 'foo' }]} end factory :vote_allowed do user vote allowed 1 end factory :vote_casted do vote_allowed vote_option end 

规格/型号/ vote_spec

 describe Vote do describe 'should return the good label' do let(:nobody) { FactoryGirl.create(:vote, visibility: 0) } it "should not be visible" do #nobody.intercom_custom_data[:visibility].should == I18n.t("votes.new.visibility_none") puts nobody.inspect puts nobody.vote_options.inspect end end end 

控制台

 Run options: exclude {:semaphore_ignore=>true} # [#] 

我不使用任何关联,任何列表,我只是强制添加options_attributes以在创建投票时自动创建vote_options。 (就像我们从浏览器创建新投票时那样)

谢谢majioa。