FactoryGirl 循环依赖和验证 [英] FactoryGirl circular dependency and validation

查看:30
本文介绍了FactoryGirl 循环依赖和验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new with FactoryGirl, in Ruby, I'm trying to write some rspec but I got some troubles with a circular dependency. I searched and tried several things, the last one generated an infinite loop and I had to shutdown my 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

spec/models/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 << VoteOption.create(vote_id: vote.id)
      #vote.save!(:validate => 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和vote_options.

This is the code which did an infinite loop. I guess that it created vote and vote_options infinitely because of the circular dependency.

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

So, I got a vote which have many vote_options (the user choices), each vote_options contains its parent id. The validation reject the creation if fields are blank, we don't have problems with this code to save a new vote/vote_options because everything is done in the same transaction.

但是,使用 rspec,我不能同时创建相互依赖的投票和投票选项行.(或者我不知道怎么做)

But, with the rspec, I can't create at the same time the vote and a vote_options rows depending of each other. (Or I don't know how to do it)

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

So, I tried to avoid the validation like this:

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

但是我遇到了一个错误:

But I got an error:

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 上找到了关于如何在 >3.3 中使用 after_create"的教程.com/questions/15003968/undefined-method-after-create-with-factorygirl 但它对我不起作用,我不应该得到投票选项不能为空"......所以我接受了查看上一个链接中链接的文档,我尝试添加 spec/factories

I tried to use after_create instead of after(:create) before but my FactoryGirl is in 4.3, so after_create doesn't exists anymore. I found a tutorial about "how use after_create in >3.3" at https://stackoverflow.com/questions/15003968/undefined-method-after-create-with-factorygirl but it doesn't works for me, I should not get the "vote options can't be blank"... So I took a look at the doc linked in the previous link and I tried to add in spec/factories

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

但我真的不明白我应该做什么,我不明白问题出在哪里.有什么想法吗?

But I don't really understand what I should do and I don't understand where is the problem. Any idea?

编辑 #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

推荐答案

您是否尝试过按照 文档?

Have you tried to do according the Association chapter of the document?

ignore do
   vote_options_count = 1
end

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

之后应该允许访问如下:

After that it should be allowed to access as follows:

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

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

NOTE: The vote_option factory must be defined as of a single, not a plural case.

这篇关于FactoryGirl 循环依赖和验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆