工厂女孩与同一父母有多个联系

时间:2015-11-20 17:56:12

标签: ruby-on-rails activerecord factory-bot

如何创建具有多个依赖于同一父级的关联的Factory?

父模型:

class Parent < ActiveRecord::Base
  has_many :codes
  has_many :parent_filters

  validates :parent, :presence => true, :uniqueness => true
end

Fitler型号:

class Filter < ActiveRecord::base
  has_many :parent_filters
  validates :filter, :presence => true, :uniqueness => true
end

ParentFilter连接模型:

class ParentFilter < ActiveRecord
  belongs_to :parent
  belongs_to :filter

  validates :filter, :presence => true
  validates :parent, :filter, :presence => true, :uniqueness => [ :scope => filter ]
end

AdhocAttribute模型:

class AdhocAttribute < ActiveRecord::Base
  has_many :adhoc_mappings

  has_many :codes, :through => :adhoc_mappings
  has_many :parent_filters, :through => adhoc_mappings

  validates :adhoc_attribute, :presence => true, :uniqueness => true
end

代码模型:

class Code < ActiveRecord::Base
  belongs_to :parent

  has_many :adhoc_mappings
  has_many :adhoc_attributes, :through => :adhoc_mappings

  validates :code, :parent, presence: true
  validates :code, uniqueness: {case_sensitive: false}
end

最后但并非最不重要的是,ad-hoc映射模型。这个模型允许每个代码为每个ParentFilter分配一个adhoc属性,这是我试图创建的工厂。这个工厂应该要求ParentFilter和Code的Parent都是相同的(我将添加一个自定义验证,以便在我获得功能工厂后强制执行)。

class AdHocMapping < ActiveRecord::Base

  belongs_to :code
  belongs_to :parent_filter
  belongs_to :adhoc_attribute

  has_one :company, :through => :parent_filter

  validates :code, :parent_filter, presence: true
  validates :code, :uniqueness => { :scope => :parent_filter }
end

如果我要使用直接的ActiveRecord创建一个AdhocMapping,我会建立起来像这样:

p = Parent.where(:parent => "Papa").first_or_create
aa = AdhocAttribute(:adhoc_attribute => "Doodle").first_or_create
f = Filter.where(:filter => "Z..W").first_or_create
c = Code.where(:code => "ZYXW", :parent => p).first_or_create
pf = ParentFilter.where(:parent => p, :filter => f).first_or_create
am = AdhocMapping(:adhoc_attribute => aa, :parent_filter => pf, :code => :c).first_or_create

以便分配给AdhocMapping的Code和ParentFilter具有相同的Parent。我已经尝试了许多不同的方法来尝试在FactoryGirl中使用它,但我似乎无法创建该对象。

这是我认为最接近我想要的工厂:

require 'faker'

FactoryGirl.define do
  factory :adhoc_mapping do |f|
    transient do
     p Parent.where(:parent => Faker::Lorem.word).first_or_create
    end

    association :parent_filter, :parent => p
    association :code, :parent => p
    association :adhoc_attribute
  end
end

它给出了Trait not registered: p

的错误

1 个答案:

答案 0 :(得分:1)

对于关联,我通常在after(:build)中使用FactoryGirl,然后我可以确切地说明应该发生什么。 association xxx经常不像我想要的那样工作,对我感到羞耻。)

所以在你的情况下,我认为你可以解决这个问题:

require 'faker'

FactoryGirl.define do
  factory :adhoc_mapping do |f|
    transient do
      default_parent { Parent.where(parent: Faker::Lorem.word).first_or_create }

      parent_filter {  FactoryGirl.build(:parent_filter, parent: default_parent) }
      code { FactoryGild.build(:code, parent: default_parent) }
      adhoc_attribute { FactoryGirl.build(:adhoc_attribute) }
    end

    after(:build) do |adhoc_mapping, evaluator|
      adhoc_mapping.parent_filter = evaluator.parent_filter
      adhoc_mapping.code = evaluator.code
      adhoc_mapping.adhoc_attribute = evaluator.adhoc_attribute
    end
  end
end

使用after(:build),它适用于FactoryGirl.createFactoryGirl.build。除了transient default_parent之外,您甚至可以在构建adhoc_mapping时明确设置您希望拥有的父级。现在,在编辑之后,您还可以将nil传递给属性,但不会被覆盖。