3

我正在尝试使用 FactoryGirl 创建一个具有 Parent has_many Entries 关联的测试数据库。此时,它正在抛出 Parent 不能为空的 ActiveRecord 验证错误。我在这个方面遇到了困难,并且尝试了很多很多方法来创建这个关联的测试数据库。我认为我很接近,但我可能甚至没有接近并且可能有基本错误,因此非常感谢任何和所有建议。

我的猜测是哈希 { parent_id: :id } 没有被传递给 Entry 工厂。那将无法通过验证。但是,我不知道事实是否如此,即使是这样,我也不知道如何解决它。在此先感谢您的帮助...

错误是:

ActiveRecord::RecordInvalid:验证失败:父级不能为空

RSpec 调用是:

before(:all) do
  rand(11..25).times { FactoryGirl.create(:parent) }
  visit "/parents?direction=asc&sort=parent_blog"  
end
after(:all)  do
  Parent.delete_all
end

父模型是:

class Parent < ActiveRecord::Base
  has_many :entries, dependent: :destroy
  accepts_nested_attributes_for :entries, :allow_destroy => :true
  validates :parent_blog, presence: true,
              uniqueness: true
end

入口模型是:

class Entry < ActiveRecord::Base
  belongs_to :parent
  validates :entry_blog,     presence:true,
            uniqueness: true
  validates :parent_id,       presence: true
end

父工厂是:

FactoryGirl.define do
  factory :parent do
    sequence(:parent_blog) { |n| "http://www.parent%.3d.com/ss" % n }
    entries { rand(5..15).times { FactoryGirl.create(:entry,  parent_id: :id) } }
  end
end

入口工厂是:

FactoryGirl.define do
  factory :entry do
    sequence(:entry_blog)      { |n| "http://www.parent%.3d.com/ss/entry%.3d" % [n, n] }
    parent_id                   { :parent_id }
  end
end
4

2 回答 2

4

对您的工厂定义的以下修改应该有效。我稍后会回来提供一些解释。

FactoryGirl.define do

  factory :parent do
    sequence(:parent_blog) { |n| "http://www.parent%.3d.com/ss" % n }
    after(:create) {|parent| rand(5..15).times {FactoryGirl.create(:entry, parent: parent)}}
  end

  factory :entry do
    sequence(:entry_blog)   { |n| "http://www.parent%.3d.com/ss/entry%.3d" % [n, n] }
    parent
  end

end

这两个更改,after:parent工厂中引入使用和使用parent代替parent_id,都是 RSpec 支持关联的示例,如https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations中所述。

至于为什么你的代码不起作用,我现在只能提供部分答案。您不能将entries其作为初始父项创建的一部分包含在内的原因是,在创建父记录之前您没有父 ID,但由于Entry验证parent_id. 换句话说,在您的父工厂评估块parent_id时尚未设置。entries

我不确定的是为什么您不能在入口工厂中替换为并相应parent地在父工厂的调用中替换为。我在提交上述内容之前尝试了该变体,但失败了:parent_idparent: parentparent_id: parent.idFactoryGirl.create

  1) test
     Failure/Error: rand(11..25).times { FactoryGirl.create(:parent) }
     ArgumentError:
       Trait not registered: parent_id
     # ./spec/factories.rb:4:in `block (4 levels) in <top (required)>'
     # ./spec/factories.rb:4:in `times'
     # ./spec/factories.rb:4:in `block (3 levels) in <top (required)>'
     # ./tmp/factory_spec.rb:5:in `block (3 levels) in <top (required)>'
     # ./tmp/factory_spec.rb:5:in `times'
     # ./tmp/factory_spec.rb:5:in `block (2 levels) in <top (required)>'

如果/当我弄清楚时,我会再次更新这个答案。

于 2013-08-17T21:57:28.283 回答
0

当我从工厂机器人 4.11 升级到 6.2 时,我遇到了这个问题。我怀疑这是因为工厂机器人 5 发生了变化Changed: use_parent_strategy now defaults to true, so by default the build strategy will build, rather than create associations

这是我的父子工厂的样子:

  factory :parent do
    sequence(:name) { |n| "Parent #{n}" }
  end

  factory :child do
    sequence(:name) { |n| "Child #{n}" }
    parent
  end

我不得不改变在规范文件中定义变量的方式。代替:

let(:parent){ create(:parent) }
let(:child) { build(:department) }

用了这个:

let(:parent){ create(:parent) }
let(:child) { build(:department, parent: parent) }
于 2021-12-21T17:57:34.500 回答