Factory Girl 与同一个 parent 有多个关联
Factory Girl with multiple associations with the same parent
如何创建一个具有多个依赖相同 parent 关联的工厂?
Parent型号:
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
Parent过滤器连接模型:
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 映射模型。该模型允许为每个代码分配一个 adhoc 属性,每个 ParentFilter,这是我试图创建的工厂。该工厂应要求 Parent 过滤器和代码的 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 的代码和 Parent过滤器具有相同的 Parent。我已经尝试了多种不同的方法来尝试让它在 FactoryGirl 中工作,但我似乎无法让它创建 object.
这是我认为最接近我想要的工厂:
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
的错误
对于关联我通常在FactoryGirl
中使用after(:build)
,这样我就可以准确地判断出应该发生什么。 (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.create
或 FactoryGirl.build
一起使用。除了 transient default_parent
,您甚至可以在构建 adhoc_mapping
时明确设置您想要的父级。现在在 edit 之后,您还可以将 nil
传递给属性,它不会被覆盖。
如何创建一个具有多个依赖相同 parent 关联的工厂?
Parent型号:
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
Parent过滤器连接模型:
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 映射模型。该模型允许为每个代码分配一个 adhoc 属性,每个 ParentFilter,这是我试图创建的工厂。该工厂应要求 Parent 过滤器和代码的 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 的代码和 Parent过滤器具有相同的 Parent。我已经尝试了多种不同的方法来尝试让它在 FactoryGirl 中工作,但我似乎无法让它创建 object.
这是我认为最接近我想要的工厂:
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
对于关联我通常在FactoryGirl
中使用after(:build)
,这样我就可以准确地判断出应该发生什么。 (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.create
或 FactoryGirl.build
一起使用。除了 transient default_parent
,您甚至可以在构建 adhoc_mapping
时明确设置您想要的父级。现在在 edit 之后,您还可以将 nil
传递给属性,它不会被覆盖。