2010-04-19 4 views
22

Je dois passer des arguments supplémentaires à factory girl pour être utilisé dans un rappel. Quelque chose comme ça (mais plus complexe vraiment):Arguments supplémentaires pour Factory Girl

Factory.define :blog do |blog| 
    blog.name "Blah" 

    blog.after_create do |blog| 
    blog.posts += sample_posts 
    blog.save! 
    end 
end 

puis créer avec quelque chose comme ceci:

Factory.create(:blog, :sample_posts => [post1, post2]) 

Toute idée comment le faire?

Répondre

32

Ceci est maintenant possible sans "hacks" grâce à des attributs transitoires (see comment on issue #49)

exemple:

FactoryGirl.define do 
    factory :user do 
    transient do 
     bar_extension false 
    end 
    name {"foo #{' bar' if bar_extension}"} 
    end 
end 

# Factory(:user).name = "foo" 
# Factory(:user, :bar_extension => true).name = "foo bar" 

Pour les versions Factory Girl < 5.0:

FactoryGirl.define do 
    factory :user do 
    ignore do 
     bar_extension false 
    end 
    name {"foo #{' bar' if bar_extension}"} 
    end 
end 

# Factory(:user).name = "foo" 
# Factory(:user, :bar_extension => true).name = "foo bar" 
+3

Ensemble utile de documents ici, y compris la façon d'accéder à un attribut transitoire de un after_create ou un autre bloc: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md – Hollownest

+1

'ignore' est obsolète. Utilisez 'transient' à la place. –

+0

@JonathanTran Merci beaucoup, j'ai édité ma réponse pour refléter les changements! – wintersolutions

2

Une option serait de créer un accesseur virtuel pour les postes supplémentaires que les contrôles crochet after_create: au lieu

class Blog 
    has_many :posts 
    attr_accessible :name, :title, ... # DB columns 
    attr_accessor :sample_posts  # virtual column 
end 

Factory.define :blog do |blog| 
    blog.name 'Blah' 

    blog.after_create do |b| 
    b.posts += b.sample_posts 
    b.save! 
    end 
end 

Factory(:blog, :sample_posts => [post1, post2]) 
+0

Pour mon exemple qui fonctionnerait, mon cas réel est un peu plus compliqué. En outre, je ne voudrais pas polluer les modèles pour les limitations de FactoryGirl. Merci quand même :) – Pablo

+1

Il suffit de polluer le modèle dans votre environnement 'test'. En fait, vous pouvez le faire ici dans 'factories.rb'. –

+0

Oh! bien sûr, les classes ouvertes :) – Pablo

1

Une autre option serait d'utiliser build de create et ajouter :autosave à la collection:

class Blog 
    has_many :posts, :autosave => true 
end 

Factory.define :blog do |blog| 
    blog.name 'Blah' 
    blog.posts { |_| [Factory.build(:post)] } 
end 

Factory(:blog, :posts => [post1, post2]) 
#or 
Factory.build(:blog, :posts => [unsavedPost1, unsavedPost2]) 
1

Si vous ouvrez la classe dans le fichier factorygirl, je suggère de le faire comme

require "user" 
class User 
    attr :post_count 
end 

de sorte que vous ouvrez la classe, au lieu de l'écraser

Questions connexes