Factory Girl 201

Lo que vas a crear

Mi segundo artículo sobre esta popular y útil gema Ruby trata sobre un par de temas más matizados que los principiantes no necesariamente deben preocuparse de inmediato cuando comienzan. Una vez más, hice todo lo posible para mantenerlo accesible a los principiantes y explicar que cada poco de gente de la jerga que se encuentra en el desarrollo impulsado por pruebas (TDD) podría tropezar.

Los temas

  • Atributos dependientes
  • Atributos transitorios
  • Atributos perezosos
  • Modificando las fábricas
  • Devoluciones de llamada
  • Asociaciones
  • Alias
  • Rasgos

Atributos dependientes

Si necesita usar valores de atributo para componer otros atributos de fábrica sobre la marcha, Factory Girl lo tiene cubierto. Solo necesita envolver el valor del atributo en un bloque e interpolar los atributos que necesita. Estos bloques tienen acceso a un evaluador-que se entrega a ellos y que a su vez tiene acceso a otros atributos, incluso transitorios.

FactoryGirl.define do factory: supervillain do name 'Karl Stromberg' passion 'biología marina' ambición 'extinción humana' motivación 'salvar los océanos' perfil "# nombre tiene una pasión por # pasión y apunta a # motivación  a través de # ambición. " end end villano = crear (: supervillano) villain.profile # =>" Karl Stromberg tiene una pasión por la biología marina y tiene como objetivo salvar los océanos a través de la extinción humana ". 

Atributos Transitorios

Creo que es justo llamarlos atributos falsos. Estos atributos virtuales también le permiten pasar opciones adicionales cuando construye sus instancias de fábrica, por supuesto, a través de un hash. La instancia en sí no se verá afectada por ellos, ya que estos atributos no se establecerán en su objeto de fábrica. Por otro lado, Factory Girl trata los atributos transitorios como los reales..

Si utiliza atributos_para, Aunque no aparecerán. Los atributos dependientes y las devoluciones de llamada pueden acceder a estos atributos falsos dentro de su fábrica. En general, son otra estrategia para mantener tus fábricas SECAS.

FactoryGirl.define do factory: supervillain do transient do megalomaniac false cat_owner false end name 'Karl Stromberg' passion 'biología marina' ambición 'extinción humana' motivación "Construyendo una civilización submarina # " y salvando al mundo "si megalómano" profile "Insane business tycoon # " - amigos con Blofeld "if cat_owner" end end villano = crear (: supervillain) villain.profile # => "Insane business tycoon" villain.motivation # => "Construyendo una civilización submarina "cat_friendly_villain = create (: supervillain, cat_owner: true) cat_friendly_villain.profile # =>" El magnate de los negocios locos: amigos con Blofeld "narcissistic_villain = create (: supervillain, megalomaniac: true) narcisistic_villain.motivation # =>" Building an con estilo de una cúpula de civilizacion: salvando al mundo" 

El ejemplo anterior resulta ser un poco más seco ya que no hubo necesidad de crear fábricas separadas para supervillanos que quieran salvar el mundo o que sean amigos de Blofeld respectivamente. Los atributos transitorios le brindan la flexibilidad de realizar todo tipo de ajustes y evitar la creación de una gran cantidad de fábricas tan similares..

Atributos perezosos

Los atributos "normales" en Factory Girl se evalúan cuando se define la fábrica. Por lo general, proporciona valores estáticos como parámetros a métodos con el mismo nombre que sus atributos. Si desea retrasar la evaluación hasta el último momento posible (cuando se instancia la instancia), deberá ingresar los atributos de sus valores a través de un bloque de código. Asociaciones y valores creados dinámicamente a partir de objetos como Fecha y hora Los objetos serán tus clientes más frecuentes para ese tratamiento perezoso..

FactoryGirl.define do factory: exploding_device do transient do do countdown_seconds 10 * 60 time_of_explosion Time.now + countdown_seconds end time_of_explosion.strft en el% de% de%.  " end end ticking_device = create (: exploding_device) ticking_device.time_of_explosion # =>" Explosión en 600 segundos a las 11:53 PM " 

Modificando las fábricas

Es probable que este no sea un caso de uso con el que te encuentres todos los días, pero a veces heredas las fábricas de otros desarrolladores y quieres cambiarlas, por ejemplo, si estás usando una gema TDD. Si sientes la necesidad de modificar estas fábricas heredadas para que se ajusten mejor a tus escenarios de prueba específicos, puedes modificarlas sin crear nuevas o usar herencia.

Usted hace esto a través de FactoryGirl.modify, y tiene que estar fuera de ese particular FactoryGirl.define Bloque que quieres cambiar. Lo que no puedes hacer es modificar. secuencia o rasgo-puede anular los atributos definidos a través de rasgo aunque. Las devoluciones de llamada en la fábrica "original" tampoco se anularán. El callback en tu Fábrica.modificar el bloque se ejecutará como el siguiente en la línea.

FactoryGirl.define do factory: spy do name 'Marty McSpy' skills 'Espionaje e infiltración' deployment_status 'Preparing mission' end end FactoryGirl.modify do secuencia: mission_deployment do | number | "Mission # number at # DateTime.now.to_formatted_s (: short)" factory final: spy do name 'James Bond' skills 'CQC and poker' favorite_weapon 'Walther PPK' body_count 'Classified' favorite_car 'Aston Martin DB9 'despliegue generar (: misión_desarrollo) final fin 

En el ejemplo anterior, necesitábamos que nuestros espías fueran un poco más "sofisticados" y usaran un mejor mecanismo para manejar la implementación. He visto ejemplos en los que los autores de gemas tuvieron que lidiar con el tiempo de manera diferente y donde fue útil modificar los objetos de fábrica simplemente anulando las cosas que necesita modificar..

Devoluciones de llamada

Las devoluciones de llamada le permiten inyectar algo de código en varios momentos del ciclo de vida de un objeto salvar, after_save, validación anterior y así. Rails, por ejemplo, ofrece una gran cantidad de ellos y hace que sea bastante fácil para los principiantes abusar de este poder..

Tenga en cuenta que las devoluciones de llamada que no están relacionadas con la persistencia de los objetos son un antipatrón conocido, y es un buen consejo no cruzar esa línea. Por ejemplo, puede parecer conveniente utilizar una devolución de llamada después de crear una instancia de algo como el usuario para enviar correos electrónicos o procesar algún pedido, pero este tipo de cosas invitan a errores y crean vínculos que son innecesariamente difíciles de refactorizar. Tal vez esa fue una de las razones por las que Factory Girl "only" te ofrece cinco opciones de devolución de llamada para jugar:

  • antes (: crear) ejecuta un bloque de código antes de que se guarde su instancia de fábrica. Activado cuando usas create (: some_object).
  • después (: crear) ejecuta un bloque de código después de que se guarda la instancia de fábrica. Activado cuando usas create (: some_object).
  • después de (: construir) ejecuta un bloque de código después de que su objeto de fábrica se haya incorporado en la memoria. Activado cuando usas ambos construir (: some_object) y create (: some_object).
  • después de (: talón) ejecuta un bloque de código después de que su fábrica haya creado un objeto aplastado. Activado cuando usas build_stubbed (: some_object).
  • custom (: your_custom_callback) ejecuta una devolución de llamada personalizada sin necesidad de anteponer antes de o después.
FactoryGirl.define do factory: mission do object 'Stopping the bad dude' proporcionada_gadgets 'Mini submarino y pistola de tiburones' después de (: build) assign_support_analyst end end 

Atención!

Tenga en cuenta que para todas las opciones de devolución de llamada, dentro de los bloques de devolución de llamada, tendrá acceso a una instancia de fábrica a través de un parámetro de bloque. Esto será útil de vez en cuando, especialmente con las asociaciones.

FactoryGirl.define do factory: double_agent do after (: stub) | double_agent | assign_new_identity (double_agent) end end 

Abajo, un Ninja tiene un montón de estrellas arrojadizas desagradables (shuriken) a su disposición. Ya que tienes un ninja Objeto en la devolución de llamada, puedes asignar fácilmente la estrella arrojadiza para que pertenezca al Ninja. Echa un vistazo a la sección sobre asociaciones Si ese ejemplo te deja con un par de signos de interrogación..

FactoryGirl.define do factory: ninja do name "Ra's al Ghul" factory: ninja_with_shuriken do transient do do_of_shuriken 10 final after (: create) do | ninja, evaluator | create_list (: shuriken, evaluator.number_of_shuriken, ninja: ninja) end end end factory: shuriken do name 'Hira-shuriken' number_of_spikes 'Four' ninja end end ninja = create (: ninja) ninja.shurikens.length # => 0 ninja = crear (: ninja_with_shuriken) ninja.shurikens.length # => 10 ninja = crear (: ninja_with_shuriken, number_of_shuriken: 20) ninja.shurikens.length # => 20 

Además, a través del objeto evaluador también tiene acceso a atributos transitorios. Eso le da la opción de pasar información adicional cuando "crea" objetos de fábrica y necesita modificarlos sobre la marcha. Eso le brinda toda la flexibilidad necesaria para jugar con asociaciones y escribir datos de prueba expresivos.

Si encuentra la necesidad de tener múltiples devoluciones de llamada en su fábrica, Factory Girl no se interpondrá en su camino, incluso las de tipo múltiple. Naturalmente, el orden de ejecución es de arriba a abajo..

FactoryGirl.define do factory: henchman do name 'Mr. Hinx 'después de (: crear) | henchman | henchman.send_on_kill_mission después de (: create) send_cleaner end end end 
FactoryGirl.define do factory: bond_girl do nombrar 'Lucia Sciarra' después de (: build) | bond_girl | bond_girl.hide_secret_documents after (: create) close_hidden_safe_compartment end end end 

El diablo está en los detalles, por supuesto. Si utiliza create (: some_object), ambos después de (: construir) y después (: crear) las devoluciones de llamada serán ejecutadas.

Se pueden agrupar múltiples estrategias de compilación para ejecutar la misma devolución de llamada también.

FactoryGirl.define do factory: spy do name 'Marty McFly' después de (: stub,: build) | spy | spy.assign_new_mission end end end 

Por último, pero no menos importante, incluso puede configurar algo como devoluciones de llamada "globales" que anulan las devoluciones de llamada para todas las fábricas, al menos en ese archivo en particular si las ha separado en varios archivos de fábrica.

fábricas / gun.rb

FactoryGirl.define do before (: stub,: build,: create) | object | object.assign_serial_number factory: spy_gun do name 'Walther PPK' ammunition '7.65mm Browning' association: owner factory: golden_gun do name 'Custom Lazar' municiones '24 -carat gold bullet 'después de (: crear) | golden_gun | golden_gun.erase_serial_number end end end end 

Atención!

Si usa la herencia para componer fábricas secundarias, las devoluciones de llamada en el padre también se heredarán.

La ultima milla

Vamos a juntarlo todo en las siguientes secciones sobre asociaciones y rasgos-si yo también me colé alias Porque era el mejor lugar sin saltar por todos lados. Si ha prestado atención y recuerda cosas del primer artículo, todo debería encajar perfectamente en su lugar ahora..

Asociaciones

Las asociaciones son esenciales para cualquier aplicación web que se respete y que tenga un poco de complejidad. Una publicación que pertenece a un usuario, una lista que tiene muchas calificaciones, etc., son los desarrolladores de Bread and Butter que tienen para el desayuno cualquier día de la semana. Visto desde esa perspectiva, resulta obvio que para escenarios más complejos, las fábricas deben ser a prueba de balas y fáciles de manejar, al menos para no meterse con su mojo TDD.

Emular asociaciones de modelos a través de Factory Girl es relativamente sencillo, diría yo. Eso en sí mismo es bastante sorprendente en mi mente. Lograr un alto nivel de facilidad y conveniencia para crear conjuntos de datos complejos hace que la práctica de TDD sea sencilla y mucho más efectiva.

La nueva Q tiene habilidades de hacker y necesita poseer una computadora decente, ¿verdad? En este caso tienes un Computadora clase y sus instancias pertenecen a instancias de la Oficial de intendencia clase. Fácil a la derecha?

FactoryGirl.define do factory: quartermaster do name 'Q' skills 'Inventing stuff' end factory: computer do model 'Custom Lenovo ThinkPad W Series' quartermaster end end 

¿Qué hay de algo un poco más complicado? Digamos que nuestros espías usan una pistola que tiene muchos cartuchos (balas).

Cartucho de clase < ActiveRecord::Base belongs_to :gun end class Gun < ActiveRecord::Base has_many :cartridges end 
FactoryGirl.define do factory: cartucho do calibre '7.65' gun end factory: gun do nombre 'Walther PPK' municiones '7.65mm Browning' calibre '7.65' factory: gun_with_ammo do transient do magazine_size 10 end after ((create) do | gun evaluador | create_list (: cartucho, evaluator.magazine_size, gun: gun) end end end end end 

Las devoluciones de llamada son bastante útiles con las asociaciones, ¿eh? Ahora puedes construir un arma con o sin municiones. A través del hash pistola: pistola usted proporcionó el cartucho Fábrica con la información necesaria para crear la asociación a través del clave externa.

spy_gun = create (: gun) spy_gun.cartridges.length # => 0 spy_gun_with_ammo = create (: gun_with_ammo) spy_gun_with_ammo.cartridges.length # => 10 

Si necesita otro tamaño de revista, puede pasarlo a través de su atributo transitorio.

big_magazine_gun = create (: gun_with_ammo, magazine_size: 20) big_magazine_gun.cartridges.length # => 20 

Entonces, ¿qué pasa con las diferentes estrategias de construcción? ¿No había algo sospechoso? Bueno, esto es lo que necesitas recordar: si usas crear Para los objetos asociados, ambos serán guardados. Asi que crear (: intendente) Construirá y salvará tanto a Q como a su ThinkPad..

Mejor uso construir, Entonces, si quiero evitar golpear la base de datos, ¿verdad? Buena idea pero construir solo se aplicaría a oficial de intendencia en nuestro ejemplo los asociados computadora todavía sería salvado. Un poco complicado, lo sé. Esto es lo que puede hacer si necesita evitar guardar el objeto asociado: especifica la estrategia de construcción que necesita para su asociación.

FactoryGirl.define do factory: quartermaster do name 'Q' skills 'Inventing stuff' end factory: computer do model 'Custom Lenovo ThinkPad W Series' asociación: quartermaster, estrategia:: build end end 

Nombra el objeto de fábrica asociado y pasa un hash con su estrategia de construcción. Necesitas usar el explícito asociación Llama para que esto funcione. El siguiente ejemplo no funcionará.

fábrica: computadora hacer modelo 'Personalizado Lenovo ThinkPad W Series' quartermaster, estrategia:: construir fin 

Ahora ambos objetos usan construir y nada se guarda en la base de datos. Podemos comprobar esa suposición utilizando nuevo record?, que devuelve cierto si la instancia no ha sido persistente.

thinkpad = build (: computer) thinkpad.new_record? # => true thinkpad.quartermaster.new_record? # => verdadero 

Mientras estamos en ello, a través de lo explícito. asociación Llame también puede consultar diferentes nombres de fábrica y cambiar atributos sobre la marcha..

FactoryGirl.define do factory: quartermaster do name 'Q' end factory: computer do model 'Custom Lenovo ThinkPad W Series' asociación: hacker, factory:: quartermaster, skills: 'Hacking' end end 

Vamos a cerrar este capítulo con un ejemplo que es polimórfico.

clase espia < ActiveRecord::Base belongs_to :spyable, polymorpic: true end class MIFive < ActiveRecord::Base has_many :spies, as: :spyable end class MISix < ActiveRecord::Base has_many :spies, as: :spyable end 
FactoryGirl.define do factory: mifive do name 'Military Intelligence, Section 5' principal_activity 'National contra-intelligence' fin de fábrica: misix do name 'Military Intelligence, Section 6' principal_activity 'Foreign anti-intelligence' end factory: mifive_spy, clase: Asociación Spy Do Name '005': Spyable, Factory:: Mifive End Factory: Misix_spy, Clase: Spy Do Name Asociación: Spyable, Factory:: Misix End End # MI5 Agents mifive = create (: Mifive) Mifive_spy = Create (: mifive_spy) mifive.spies << mifive_spy mifive.name # => "Inteligencia militar, Sección 5" mifive_spy.name # => '005' mifive.spies.length # => 1 mifive.spies.first.name # => '005' # MI6 agents misix = create (: misix) misix_spy_01 = create (: misix_spy, nombre: '007') misix_spy_02 = create (: misix_spy) misix.spies << misix_spy_01 misix.spies << misix_spy_02 misix.name # => "Inteligencia militar, Sección 6" misix.spies.length # => 2 misix_spy_01.name # => '007' misix_spy_02.name # => '006' misix.spies.first.name # => '007' 

No se sienta mal si este necesita un poco más de tiempo para incorporarse. Recomiendo ponerse al día con las Asociaciones Polimórficas si no está seguro de lo que está pasando aquí..

Alias

Los alias para sus fábricas le permiten ser más expresivo sobre el contexto en el que está usando sus objetos de fábrica. Solo necesita proporcionar un hash de nombres alternativos que describan mejor la relación entre los objetos asociados..

Digamos que tienes un :agente fábrica y un : law_enforcement_vehicle fábrica. ¿No sería bueno referirse al agente como :propietario ¿En el contexto de estos coches? En el siguiente ejemplo, lo contrasté con un ejemplo sin un alias.

FactoryGirl.define do factory: agent, aliases: [: owner] do name 'Fox Mulder' job 'Chasing bad dudes' special_skills 'Investigation and intelligence' factory: double_O_seven do name 'James Bond' end end factory: law_enforcement_vehicle do nombre 'Oldsmobile Achieva 'kind' Compact car ': propietario final factory: spy_car do name' Aston Martin DB9 'kind' Sports car 'double_O_seven end end 

Atención!

No olvide agregar dos puntos frente a la fábrica de alias (:propietario) Cuando los usas para asociaciones en tus fábricas. La documentación y muchas publicaciones de blog los utilizan sin dos puntos en estos casos. Todo lo que obtienes es probablemente un NoMethodError porque le falta un método de establecimiento para ese alias ahora. (Será mejor que abra una solicitud de extracción). La primera vez que me topé con esto, me desconcertó y me tomó un poco para superarlo. Recuerde a veces desconfiar selectivamente de la documentación y de las publicaciones del blog. Atentamente también, por supuesto..

Creo que estarás de acuerdo en que usar alias no solo lee mejor sino que también te da a ti oa la persona que te persigue un poco más de contexto sobre los objetos en cuestión. Sí, necesitas usar plural : alias también si tienes un solo alias.

Podrías escribir esto también de manera un poco diferente, mucho más verbalmente.

factory: agent, aliases: [: mulder] do name 'Fox Mulder' trabajo 'Chasing bad dudes' special_skills 'Investigation and intelligence' end factory: law_enforcement_vehicle do name 'Oldsmobile Achieva' tipo 'Compact car' asociación: propietario, fábrica:: agente de fin 

Bueno, no tan limpio, ¿verdad??

Por supuesto, también puede utilizar estos alias para "construir" objetos de fábrica de inmediato..

fbi_agent = create (: mulder) fbi_agent.name # => 'Fox Mulder' 

En el contexto de los comentarios, un :usuario podría ser referido como : comentarista, en el caso de un :crimen una :usuario podría ser alias como :sospechar, y así. En realidad, no es ciencia espacial, más bien como un práctico azúcar sintáctica que disminuye la tentación de duplicar.

Rasgos

Esta es una de mis cosas favoritas de Factory Girl. En pocas palabras, los rasgos son bloques tipo lego para construir sus fábricas y mezclar su comportamiento. Son listas separadas por comas de rasgos / atributos de símbolos que desea agregar a una fábrica en particular, y también están definidas en el (los) archivo (s) de su fábrica..

En mi mente, rasgo es la función más poderosa y conveniente para mantener tus datos de fábrica SECOS mientras se expresan al mismo tiempo. Le permite agrupar grupos de atributos, darles nombres separados y reutilizarlos donde quiera. ¿Recuerdas cuando te insté a que definieras objetos de fábrica? Los rasgos te ayudarán a lograr exactamente eso sin sacrificar ninguna conveniencia..

FactoryGirl.define do factory: spy_car do model 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat true rasgo: submarine do eection_seat false water_resistant '100 m' submarinismo '12' machine_gun true rate_of_fire '1,500 RPM' tank_armour true end rasgo: oculto do active_camouflage true radar_signature 'reducido' engine 'silenced' end trait: night_vision do infrared_sensors true heads_up_display true end end end 

Como puede ver, si desea cambiar algunos atributos que se distribuyen en varios objetos, puede hacerlo ahora en un lugar central. No es necesaria la cirugía de escopeta. Gestionar el estado a través de rasgos no podría ser más conveniente.

Con esa configuración, puedes construir autos espía bastante elaborados mezclando los distintos paquetes de atributos como quieras, sin duplicar nada a través de la creación de todo tipo de nuevas fábricas que dan cuenta de todas las opciones que necesitas..

invisible_spy_car = create (: spy_car,: cloaked,: night_vision) diving_spy_car = create (: spy_car,: submarine,: cloaked) tank_spy_car = create (: spy_car,: armas,, night_vision) 

Puedes usar rasgos con crear, construir, build_stubbed y atributos_para. Si Q se vuelve inteligente, también puede anular atributos individuales simultáneamente pasando un hash.

build (: spy_car, submarine, ejection_seat: true) 

Para las combinaciones de rasgos que se producen con mucha frecuencia en una fábrica en particular, también puede crear fábricas infantiles con nombres que representen mejor los diversos conjuntos de conjuntos de datos. De esa forma, agrupará sus rasgos una sola vez, en lugar de hacerlo todo el tiempo cuando cree datos de prueba..

FactoryGir.define do factory: spy_car do model 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat verdadero rasgo: submarino do ... end rasgo: armado do ... end rasgo: encubierto do ... end rasgo: night_vision do ... end end factory: invisible_spy_car, rasgos: [: encubierto,: night_vision] factory: diving_spy_car, rasgos: [: submarine,: manto]] factory: tank_spy_car, rasgos: [: weaponized,: night_vision] factory: ultimate_spy_car, traits: [: shaked ,: night_vision,: submarino,: armado] fin 

Esto le permite crear estos objetos de forma más concisa, y también es más legible.

build_stubbed (: invisible_spy_car) create (: ultimate_spy_car) 

En lugar de:

build_stubbed (: spy_car,: cloaked,: night_vision) create (: spy_car,: cloaked,: night_vision,: submarine,: armas) 

Lee mucho mejor, no? Especialmente cuando no hay nombres de variables involucrados.

Incluso puede reutilizar rasgos como atributos en otros rasgos y fábricas. Si define los mismos atributos para múltiples rasgos, el último definido tendrá prioridad, por supuesto.

FactoryGirl.define do factory: spy_car do model 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat verdadero rasgo: submarino do ... end rasgo: armado do ... end rasgo: encubierto do ... end rasgo: night_vision do ... rasgo final: mobile_surveillance do cloaked night_vision signal_detector true signal_analyzer true wifi_war_driver true license_plate_reader true mini_drone true end end factory: ultimate_spy_car, padre:: spy_car do car_plane verdadero submarino armado mobile_surveillance final fin 

Presta atención a vigilancia móvil rasgo, que reutiliza el encapotado y Vision nocturna rasgos-básicamente como un atributo. También el ultimate_spy_car fábrica, que me separé de la spy_car La definición de fábrica para la diversión esta vez, reutiliza todos los rasgos más un atributo adicional que la hace volar también. Magia de película pura, o tal vez debería decir magia de Factory Girl.

Crear lista y build_list También puede hacer uso de rasgos. El segundo parámetro debe ser el número de instancias de fábrica que desee.

create_list (: spy_car, 3,: night_vision) build_list (: spy_car, 4,: submarine,: cloaked) 

¿No sería genial usar asociaciones con rasgos? Por supuesto, puede empaquetar devoluciones de llamada y asociaciones perfectamente en rasgos. Duh!

FactoryGirl.define do factory: cartucho del tipo municiones de pistola de calibre pequeño 'calibre' 7.65 'proyectil' Líder 'fábrica de armas: golden_cartridge do proyectil Asociación' Gold ': gun,: golden end end factory: gun do name' Walther PPK 'municiones '7.65mm Browning' calibre '7.65' transient do do magazine_size 10 end rasgo: golden do name 'Custom Lazar' municiones '23 -carat gold bullet 'trait del final: with_ammo do after (: create) do | gun, evaluator | create_list (: cartridge, evaluator.magazine_size, gun: gun) end rasgo final: with_golden_ammo do after (: create) do | golden_gun, evaluator | create_list (: golden_cartridge, evaluator.magazine_size, gun: golden_gun) end end end end end 

Cómo usarlos ya debería ser aburrido.

 cartridge = create (: cartridge) cartridge.projectile # => 'Lead' cartridge.gun.name # => 'Walther PPK' cartridge.gun.ammunition # => '7.65mm Browning' cartridge.gun.caliber # => ' 7.65 'golden_cartridge = create (: golden_cartridge) golden_cartridge.projectile # =>' Gold 'golden_cartridge.gun.name # =>' Custom Lazar 'golden_cartridge.gun.ammunition # => '23 -carat gold bullet' golden_cartridge.gun.caliber # => '7.65' gun_with_ammo = create (: gun,: with_ammo) gun_with_ammo.name # => 'Walther PPK' gun_with_ammo.ammunition # => '7.65mm Browning'. first.projectile # => 'Lead' gun_with_ammo.cartridges.first.caliber # => '7.65' golden_gun_with_golden_ammo = create (: gun,: golden,: with_golden_ammo) de los alimentos en la que se encuentra o en la que se encuentra. > '24-bullet gold bullet 'golden_gun_with_golden_ammo.cartridges.length # => 10 golden_gun_with_golden_ammo.cartridges.first.projectile # =>' Gold ' golden_gun_with_golden_ammo.cartridges.first.caliber # => '7.65' 

Pensamientos finales

Últimas palabras de sabiduría: el cambio es su compañero constante, ya que la necesidad de cambiar atributos o tipos de datos sucede todo el tiempo. Las decisiones de diseño como estas evolucionan. Los rasgos le aliviarán el dolor y le ayudarán a administrar sus conjuntos de datos.

Imagínese si hubiera usado un hash de opciones para la creación de instancias y ese requisito cambió totalmente. ¿Cuántos lugares potenciales en sus exámenes podrían romperse y ahora necesitarán atención? Recto hacia arriba, rasgo es una herramienta muy efectiva para eliminar la duplicación en su conjunto de pruebas. ¡Pero con toda esa conveniencia, no sea perezoso y olvide sus pruebas de unidad en las columnas representadas por sus rasgos! De esa manera, les brinda la misma cantidad de cuidado que los atributos básicos necesarios para los objetos válidos..

Hay mucho más por descubrir en Factory Girl, y estoy seguro de que ahora está más que bien equipado para armar las piezas cuando las necesite. Diviértete jugando con esta joya. Espero que sus hábitos de TDD se beneficien de ello..