Как я могу построить/создать ассоциацию «многие ко многим» в factory_girl?

У меня есть модель 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

person aarona    schedule 30.07.2010    source источник


Ответы (2)


Хорошо, кажется, я понимаю, о чем вы сейчас спрашиваете. Что-то вроде этого должно работать (не проверено, но я сделал что-то подобное в другом проекте):

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

Как уже отмечалось, использование третьей отдельной фабрики необязательно. В моем случае я не всегда хотел генерировать ассоциацию для каждого теста, поэтому я создал отдельную фабрику, которую использовал только в нескольких конкретных тестах.

person Robert Speicher    schedule 07.08.2010
comment
Это работает, ты молодец! А всем, кому интересно, загляните в этот блог: robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl или railsondave.blogspot.com/2009/05/ - person aarona; 08.08.2010

Используйте обратный вызов (дополнительную информацию см. в документах 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, который создает реалистичные имена и фамилии, а также электронную почту. -почтовые адреса для вас.

person Robert Speicher    schedule 31.07.2010
comment
Я не думаю, что это именно то, что я ищу. Я отредактировал свой вопрос для ясности. +1 за фальшивый драгоценный камень. Я хотел бы выяснить, как это сделать, чтобы лучше понять, как работает factory_girl. - person aarona; 08.08.2010