最终,我正在尝试使用FactoryGirl创建一个通过连接模型进行关联的对象实例。这是我has_many :through
的标准示例。
class Partition < ActiveRecord::Base
has_many :lists
has_many :configs, through: :lists
end
class List < ActiveRecord::Base
belongs_to :partition
belongs_to :config
end
class Config < ActiveRecord::Base
has_many :lists
has_many :partitions, through: :lists
end
在我的规格中,我这样做:
config = FactoryGirl.create(:config)
partition = FactoryGirl.create(:partition, configs: [config])
创建分区的行失败,Validation failed: Lists is invalid
。而且我认为原因是它创造了无序的东西。这是我的验证,它指的是:
class List < ActiveRecord::Base
validates :partition_id, presence: true, uniqueness: { scope: :config_id }
end
重要说明:这似乎在Rails 3中运行良好。我正在尝试将我们的应用程序升级到Rails 4,并且它在Rails 4中失败。
如果我将工厂更改为:
,我可以使其工作config = FactoryGirl.create(:config)
partition = FactoryGirl.build(:partition, configs: [config])
partitions.save
然后一切似乎都很好,但那不是我想要做的。我已经读过,在我的工厂,我可以这样做:
factory :partition do |partition|
...
partition.after_create do |p|
p.configs << :config # Does not work, see update below
end
end
但是如果可能的话,我想把我的配置传递给我的工厂,如果可能的话。
重申我的问题:如何使用FactoryGirl在Rails 4中创建一个has_many through:
关系为{?1}}的对象?
更新
如果我改变我的工厂:
factory :partition do
...
after(:create) do |p|
p.build_configurations << FactoryGirl.create(:tcid)
end
end
然后,只有当我将工厂创建改为:
时,测试才会通过FactoryGirl.create(:partition)
但我希望的目标是:
config = # Get an instance of a Config
FactoryGirl.create(:partition, configs: [config])
更新2
似乎你 CAN 就像我想要的那样创建工厂,但我认为时机必须关闭。如果我从List
删除了验证,Partition
工厂在我传入configs: [config]
时工作正常。
在保存配置之前,工厂似乎正在尝试保存列表(验证的位置)?想法?
答案 0 :(得分:0)
我相信在您的联接表中添加inverse_of
可以解决问题。像这样使用它:
class List < ActiveRecord::Base
belongs_to :partition, inverse_of: :lists
belongs_to :config, inverse_of: :lists
end
答案 1 :(得分:0)
会这样吗?
factory :partition do
# partition init goes here...
after(:create) do |partition, evaluator|
config = create :config
list = create :list, partition: partition, config: config
end
end
我没有对此进行过测试,因此您必须先试一试,看看它是否适合您。这个概念首先创建配置记录,然后创建列表项。
使用评估程序,您可以允许自己传递自定义配置,而不是在Config工厂中使用默认配置,如下所示:
factory :partition do
# partition init goes here...
transient do
custom_config: false
end
after(:create) do |partition, evaluator|
if evaluator.custom_config
config = custom_config
else
config = create :config
end
list = create :list, partition: partition, config: config
end
end
这将使你能够做到这样的事情:
config = # Some custom built config
partition = FactoryGirl.create(:partition, custom_config: config)
瞬态属性非常适合创作之后,我已经使用了很多,一旦你得到它们,你会喜欢它们给你的多功能性。