2010-04-19 13 views
22

Necesito pasar argumentos extra a la chica de la fábrica para utilizar en una devolución de llamada. Algo como esto (pero más compleja en realidad):Argumentos adicionales para Factory Girl

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

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

y cree que con algo como esto:

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

Alguna idea de cómo lo hacen?

Respuesta

32

Ahora esto es posible sin ningún tipo de "hacks", gracias a los atributos transitorios (see comment on issue #49)

ejemplo:

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" 

Para las versiones 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

Conjunto útil de documentos aquí, que incluye cómo acceder a un atributo transitorio de un after_create u otro bloque: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md – Hollownest

+1

'ignore' está en desuso. Use 'transient' en su lugar. –

+0

@JonathanTran ¡Muchas gracias, edité mi respuesta para reflejar los cambios! – wintersolutions

2

Una opción sería la creación de un descriptor de acceso virtual para mensajes adicionales que los controles after_create de gancho:

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

Para mi ejemplo que funcionaría, mi caso real es un poco más complicado. Además, no me gustaría contaminar los modelos por las limitaciones de FactoryGirl. Gracias de todos modos :) – Pablo

+1

Solo necesitas contaminar el modelo en tu entorno de prueba. De hecho, puedes hacerlo allí mismo en 'factories.rb'. –

+0

¡Oh! por supuesto, las clases abiertas :) – Pablo

1

Otra opción sería utilizar build en lugar de create y añadir :autosave a la colección:

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 está abriendo la clase dentro del archivo factorygirl, sugiero hacerlo como

require "user" 
class User 
    attr :post_count 
end 

por lo que está abriendo la clase, en lugar de sobrescribir que

Cuestiones relacionadas