20

这是 2 个简单的模型:

class Post < ActiveRecord::Base
  has_one :asset, :dependent => :destroy

  validates :asset, presence: true
end

class Asset < ActiveRecord::Base
  belongs_to :post
end

我正在尝试创建这样的工厂:

  factory :post do
    # fields...

    asset { FactoryGirl.create(:asset) }
  end

  factory :asset do
    # fields...

    post
  end

但是,运行规范会进入一个循环。

我也试过这个:

  factory :post do
    # fields...

    before(:create) do |post, evaluator|
      FactoryGirl.create_list(:asset, 1, post: post)
    end
  end

但最终出现“验证失败:资产不能为空白”。

我如何代表我的情况?

4

4 回答 4

35

我使用 after(:build) 回调解决了这个问题。

factory :post do
    # fields...
    after(:build) do |post|
      post.asset ||= FactoryGirl.build(:asset, :post => post)
    end
end

factory :asset do
    # fields...
    after(:build) do |asset|
      asset.post ||= FactoryGirl.build(:post, :asset => asset)
    end
end

通过这种方式,关联对象将在保存所属类之前创建,因此验证通过。

于 2013-06-13T20:13:46.627 回答
2

验证失败,因为在FactoryGirl创建时Post,必须存在资产。因此,在您的FactoryGirl定义中,您可以Asset在创建Post. 插入类似FactoryGirl post.rb文件的内容:

asset { FactoryGirl.create(:asset) }

或者

您可以在规范文件中创建一个Asset作为Post声明的一部分,如下所示:

asset = FactoryGirl.create(:asset)

FactoryGirl.create(:post, :asset => asset)

谢谢。

于 2013-06-11T02:55:37.603 回答
0

您可以通过如下方式传入子关联来预加载子关联:

FactoryGirl.define do
  factory :post do
    asset { Asset.create! }
  end
end

(更好的是,使用资产工厂来生成它的关联资产并预先设置详细信息)。

另一种手动方式是通过 FactoryGirl.create(:asset) 创建资产,并将其传递给变量创建,即:

asset = FactoryGirl.create(:asset)
post = FactoryGirl.create(:post, asset: asset)
于 2013-06-11T02:42:48.853 回答
0

该错误Validation failed: Asset can't be blank是因为看起来您的工厂中的关联倒退了。

factory :post do
  # fields...
end

因此,当您创建 a 时post,没有asset因此验证失败。尝试这个

factory :post do
# fields...
  asset
end

看看这个wiki 页面和关联部分。它还解释了关联之间createbuild与关联的区别

于 2013-06-11T02:43:42.127 回答