代码之家  ›  专栏  ›  技术社区  ›  aarona

我怎样才能在工厂里建立一个多对多的联系?

  •  2
  • aarona  · 技术社区  · 15 年前

    我有一个 Person 与多对多关系的模型 Email 我想创建一个工厂,让我为这个人生成一个名字和姓氏(这已经完成了),并创建一个基于那个人名字的电子邮件地址。以下是我为创建一个 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
    
    2 回复  |  直到 15 年前
        1
  •  3
  •   Robert Speicher    15 年前

    好吧,我想我明白你现在的要求了。类似这样的事情应该有效(未经测试,但我在另一个项目中做过类似的事情):

    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
    

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

        2
  •  2
  •   Robert Speicher    15 年前

    使用回调(有关详细信息,请参阅fg docs)。回调通过了正在构建的当前模型。

    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 它可以为您创建真实的名字、姓氏和电子邮件地址。