2010-07-30 17 views
2

J'ai un modèle Person qui a une relation plusieurs-à-plusieurs avec un modèle Email et je veux créer une usine qui me permet de générer un prénom et un nom pour la personne (ceci est déjà fait) et créer une adresse e-mail cela est basé sur le nom de cette personne. Voici ce que j'ai pour créer un nom de person:Comment puis-je créer/créer une association many-to-many dans factory_girl?

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 

Répondre

3

Ok, je pense que je comprends ce que vous demandez maintenant. Quelque chose comme cela devrait fonctionner (non testé, mais je l'ai fait quelque chose de similaire dans un autre projet):

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 

Comme il est indiqué, à l'aide d'un tiers, une usine séparée est facultative. Dans mon cas, je ne voulais pas toujours générer l'association pour chaque test, donc j'ai fait une usine séparée que je n'ai utilisée que dans quelques tests spécifiques.

+0

Ça marche, vous rock! Et pour tous ceux qui sont intéressés, consultez aussi ce blog: http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl ou http://railsondave.blogspot.com/2009/ 05/creation-hasmany-par-usines-avec.html – DJTripleThreat

2

Utilisez un rappel (voir FG docs pour plus d'informations). Les rappels sont passés au modèle en cours de construction.

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 

Je pense que cela fonctionne.

Vous pouvez également vous épargner du travail en regardant en utilisant le Faker gem qui crée des prénoms et des adresses e-mail réalistes pour vous.

+0

Je ne pense pas que ce soit ce que je cherche exactement. J'ai édité ma question pour plus de clarté. +1 pour le bijou faker bien. Je voudrais comprendre comment faire ceci pour que je puisse mieux comprendre comment fonctionne factory_girl. – DJTripleThreat