如何在factory_girl中构建/创建多对多关联?

我有一个与Email模型有多对多关系的Person模型,我想创建一个工厂,让我为该人生成名字和姓氏(已经完成),并创建一个电子邮件地址,基于那个人的名字。 以下是我创建一个person姓名的方法:

 Factory.sequence :first_name do |n| first_name = %w[FirstName1 FirstName2] # ... etc (I'm using a real subset of first names) first_name[(rand * first_name.length)] end Factory.sequence :last_name do |n| last_name = %w[LastName1 LastName2] # ... etc (I'm using a real subset of last names) last_name[(rand * last_name.length)] end Factory.define :person do |p| #p.id ??? p.first_name { Factory.next(:first_name) } p.last_name { Factory.next(:last_name) } #ok here is where I'm stuck #p.email_addresses {|p| Factory(:email_address_person_link) } end Factory.define :email_address_person_link do |eapl| # how can I link this with :person and :email_address ? # eapl.person_id ??? # eapl.email_address_id ??? end Factory.define :email_address do |e| #how can I pass p.first_name and p.last_name into here? #e.id ??? e.email first_name + "." + last_name + "@test.com" end 

好的,我想我明白你现在在问什么。 像这样的东西应该工作(未经测试,但我在另一个项目中做了类似的事情):

 Factory.define :person do |f| f.first_name 'John' f.last_name 'Doe' end Factory.define :email do |f| end # This is optional for isolating association testing; if you want this # everywhere, add the +after_build+ block to the :person factory definition Factory.define :person_with_email, :parent => :person do |f| f.after_build do |p| p.emails << Factory(:email, :email => "#{p.first_name}.#{p.last_name}@gmail.com") # OR # Factory(:email, :person => p, :email => "#{p.first_name}.#{p.last_name}@gmail.com") end end 

如上所述,使用第三个独立工厂是可选的。 在我的情况下,我并不总是想为每个测试生成关联,所以我创建了一个单独的工厂,我只在一些特定的测试中使用。

使用回调(有关详细信息,请参阅FG文档)。 回调被传递给正在构建的当前模型。

 Factory.define :person do |p| p.first_name { Factory.next(:first_name) } p.last_name { Factory.next(:last_name) } p.after_build { |m| p.email_addresses << "#{m.first_name}.#{m.last_name}@test.com" } end 

我认为这很有效。

您还可以通过查看使用Faker gem来为自己节省一些工作,它会为您创建真实的名字和姓氏以及电子邮件地址。