Fille d'usine 201

Ce que vous allez créer

Mon deuxième article sur ce bijou populaire et utile, Ruby, traite de quelques sujets plus nuancés que les débutants ne doivent pas nécessairement se préoccuper immédiatement lorsqu'ils commencent. Encore une fois, j'ai fait de mon mieux pour que ce soit accessible aux débutants et que j'explique que chaque personne qui parle pour la première fois en développement piloté par les tests (TDD) peut trébucher.

Les sujets

  • Attributs dépendants
  • Attributs transitoires
  • Attributs paresseux
  • Modification des usines
  • Rappels
  • Les associations
  • Alias
  • Traits

Attributs dépendants

Si vous devez utiliser des valeurs d'attribut pour composer d'autres attributs d'usine à la volée, Factory Girl est à votre disposition. Vous devez simplement envelopper la valeur de l'attribut dans un bloc et interpoler les attributs dont vous avez besoin. Ces blocs ont accès à un évaluateur-qui leur est cédé - et qui à son tour a accès à d’autres attributs, même transitoires.

FactoryGirl.define do factory: supervillain do name passion 'Karl Stromberg' passion 'biologie marine' ambition 'extinction humaine' motivation 'sauver les océans' "# name" a une passion pour # passion et vise à # # motivation  par # ambition. " end end villain = créer (: supervillain) villain.profile # =>" Karl Stromberg se passionne pour la biologie marine et cherche à sauver les océans par l'extinction de l'homme. " 

Attributs transitoires

Je pense qu'il est juste de les appeler de faux attributs. Ces attributs virtuels vous permettent également de transmettre des options supplémentaires lors de la construction de vos instances d'usine, via un hachage bien sûr. L'instance elle-même n'en sera pas affectée, car ces attributs ne seront pas définis sur votre objet d'usine. D'autre part, Factory Girl traite les attributs transitoires comme de vrais attributs..

Si tu utilises attributs_pour, ils ne viendront pas cependant. Les attributs dépendants et les callbacks peuvent accéder à ces faux attributs dans votre usine. Globalement, ils constituent une autre stratégie pour garder vos usines au sec.

FactoryGirl.define do factory: supervillain do transitient do megalomaniac false propriétaire du chat false nom final "passion de Karl Stromberg" "biologie marine" ambition "extinction humaine" motivation "Construire une civilisation sous-marine # " et sauver le monde "si mégalomane" profile "Insane business tycoon # " - amis avec Blofeld "si cat_owner" end end villain = crée (: supervillain) villain.profile # => "Ingénieur d \ 'affaires fou" villain.motivation # => "Construire une civilisation sous-marine "cat_friendly_villain = create (: supervillain, cat_owner: true) cat_friendly_villain.profile # =>" Un homme d'affaires insensé - amis avec Blofeld "narcissistic_villain = create (: supervillain, mégalomane: true) narcissistic_villain.motiving #:" colorant " sauver le monde" 

L'exemple ci-dessus s'avère un peu plus sec, car il n'était pas nécessaire de créer des usines distinctes pour les supervillains qui veulent respectivement sauver le monde ou qui sont amis avec Blofeld. Les attributs transitoires vous donnent la possibilité de faire toutes sortes d’ajustements et d’éviter de créer une multitude d’usines très semblables..

Attributs paresseux

Les attributs «normaux» dans Factory Girl sont évalués lorsque la fabrique est définie. Vous fournissez généralement des valeurs statiques en tant que paramètres de méthodes portant le même nom que vos attributs. Si vous souhaitez différer l'évaluation jusqu'au dernier moment possible, lorsque l'instance est instanciée, vous devrez alimenter leurs attributs via un bloc de code. Associations et valeurs créées dynamiquement à partir d'objets tels que Date et heure les objets seront vos clients les plus fréquents pour ce traitement paresseux.

FactoryGirl.define do factory: exploding_device do transitient do countdown_seconds 10 * 60 time_of_explosion Time.now + countdown_seconds end time_of_explosion "Exploser dans # countdown_seconds secondes # time_of_explosion.strftime (" à% I:%% de%)  " end end ticking_device = create (: exploding_device) ticking_device.time_of_explosion # =>" Exploser en 600 secondes à 23h53 " 

Modification des usines

Ce n'est probablement pas un cas d'utilisation que vous rencontrerez tous les jours, mais parfois, vous héritez des fabriques d'autres développeurs et vous souhaitez les modifier, par exemple si vous utilisez une gemme TDD'd. Si vous ressentez le besoin de modifier ces anciennes usines pour mieux les adapter à vos scénarios de test spécifiques, vous pouvez les modifier sans en créer de nouvelles ni utiliser l'héritage..

Vous faites cela via FactoryGirl.modify, et il doit être en dehors de ce particulier FactoryGirl.define bloquer que vous voulez changer. Ce que vous ne pouvez pas faire, c'est modifier séquence ou trait-vous pouvez remplacer les attributs définis via trait bien que. Les rappels sur l'usine «d'origine» ne seront pas non plus annulés. Le rappel dans votre Factory.modify bloc sera juste exécuté comme prochain en ligne.

FactoryGirl.define do factory: espion do nomme compétences 'Marty McSpy' Espionnage et infiltration 'statut_déploiement' Préparation de la mission 'fin FactoryGirl.modify séquence: mission_deployment do | number | "Mission # numéro à # DateTime.now.to_formatted_s (: short)" fin de fabrique: nom d'utilisateur "James Bond", compétences "CQC" et poker "favorite_weapon", Walther PPK "body_count", "favourites", Aston Martin DB9 'deployment generate (: mission_deployment) end end 

Dans l'exemple ci-dessus, nous avions besoin que nos espions soient un peu plus «sophistiqués» et utilisent un meilleur mécanisme pour gérer leur déploiement. J'ai vu des exemples dans lesquels les auteurs de gemmes ont dû composer avec le temps différemment et où il était pratique de modifier des objets d'usine en remplaçant simplement des éléments à modifier..

Rappels

Les rappels vous permettent d’injecter du code à différents moments du cycle de vie d’un objet. enregistrer, after_save, avant_validation etc. Rails, par exemple, en offre un grand nombre et permet aux novices d’abuser facilement de ce pouvoir..

Gardez à l'esprit que les rappels qui ne sont pas liés à la persistance des objets constituent un anti-modèle connu, et il est conseillé de ne pas dépasser cette ligne. Par exemple, il peut sembler pratique d’utiliser un rappel après avoir instancié quelque chose comme un utilisateur pour envoyer des courriels ou traiter une commande, mais ce genre de choses invite des bogues et crée des liens qui sont inutilement difficiles à refactoriser. C’est peut-être une des raisons pour lesquelles Factory Girl «uniquement» vous offre cinq options de rappel avec lesquelles vous pouvez jouer:

  • before (: créer) exécute un bloc de code avant que votre instance d'usine ne soit enregistrée. Activé lorsque vous utilisez create (: some_object).
  • after (: créer) exécute un bloc de code après la sauvegarde de votre instance d'usine. Activé lorsque vous utilisez create (: some_object).
  • après (: build) exécute un bloc de code une fois que votre objet usine a été construit en mémoire. Activé lorsque vous utilisez les deux build (: some_object) et create (: some_object).
  • après (: stub) exécute un bloc de code après que votre usine a créé un objet stubbed. Activé lorsque vous utilisez build_stubbed (: some_object).
  • custom (: your_custom_callback) exécute un rappel personnalisé sans avoir à ajouter de préfixe avant ou après.
FactoryGirl.define do factory: la mission a pour objectif "Arrêter le méchant" avec "mini sous-marin et un pistolet de requin" après_: (build) assign_support_analyst end end 

Attention!

Notez que pour toutes les options de rappel, à l'intérieur des blocs de rappel, vous aurez accès à une instance de la fabrique via un paramètre de bloc. Cela sera utile de temps en temps, en particulier avec les associations.

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

En bas, un Ninja a à sa disposition un groupe d’étoiles filantes (shuriken). Depuis que tu as ninja objet dans le rappel, vous pouvez facilement attribuer l'étoile de projection à appartenir au Ninja. Jetez un coup d’œil à la section sur les associations si cet exemple vous laisse avec quelques points d'interrogation.

FactoryGirl.define do factory: ninja do name "Ra's al Ghul" fabrique: ninja_with_shuriken do transitient do number_of_shuriken 10 fin après (: create) do | ninja, évaluateur | create_list (: shuriken, evaluator.number_of_shuriken, ninja: ninja) fin fin usine: shuriken nommez 'Hira-shuriken' nombre_de_spikes 'Quatre' ninja fin fin ninja = créer (: ninja) ninja.shurikens.length # => 0 ninja = create (: ninja_with_shuriken) ninja.shurikens.length # => 10 ninja = create (: ninja_with_shuriken, number_of_shuriken: 20) ninja.shurikens.length # => 20 

De plus, via l'objet évaluateur, vous avez également accès à des attributs transitoires. Cela vous donne la possibilité de transmettre des informations supplémentaires lorsque vous «créez» des objets d'usine et que vous devez les modifier à la volée. Cela vous donne toute la flexibilité nécessaire pour jouer avec les associations et écrire des données de test expressives.

Si vous avez besoin de plusieurs rappels sur votre usine, Factory Girl ne vous gêne pas, même plusieurs types. Naturellement, l'ordre d'exécution est de haut en bas.

FactoryGirl.define do factory: l'homme de main se nomme 'M. Hinx 'après (: create) | henchman | henchman.send_on_kill_mission après (: create) send_cleaner end end 
FactoryGirl.define do factory: bond_girl ne nommez 'Lucia Sciarra' qu'après (: build) | bond_girl | bond_girl.hide_secret_documents after (: create) close_hidden_safe_compartment end end 

Le diable est dans les détails, bien sûr. Si tu utilises create (: some_object), tous les deux après (: build) et after (: créer) les rappels seront exécutés.

Plusieurs stratégies de construction peuvent être associées pour exécuter le même rappel.

FactoryGirl.define do factory: spy ne nommer 'Marty McFly' après (: stub,: build) | spy | spy.assign_new_mission end end 

Enfin et surtout, vous pouvez même configurer quelque chose comme des rappels «globaux» qui annulent les rappels pour toutes les usines, du moins dans ce fichier particulier si vous les avez séparées en plusieurs fichiers d'usine..

usines / gun.rb

FactoryGirl.define do before (: stub,: build,: create) | object | object.assign_serial_number usine: spy_gun nomme des munitions 'Walther PPK' '7.65mm Browning' association: propriétaire usine: golden_gun nomme des munitions 'Custom Lazar' '24 - carat gold bullet 'après (: create) | golden_gun | golden_gun.erase_serial_number fin fin fin 

Attention!

Si vous utilisez l'héritage pour composer des fabriques enfants, les rappels sur le parent seront également hérités.

Le dernier kilomètre

Rassemblons le tout dans les sections suivantes sur les associations et traits-oui, j'ai aussi faufilé alias parce que c'était le meilleur endroit sans sauter partout. Si vous avez prêté attention aux documents du premier article et que vous vous en souvenez, tout devrait bien se mettre en place maintenant..

Les associations

Les associations sont essentielles à toute application Web qui se respecte et qui présente un peu de complexité. Un article qui appartient à un utilisateur, une liste qui a de nombreuses cotes, etc., sont ceux que les développeurs de pain et de beurre ont pour le petit-déjeuner tous les jours de la semaine. Vu sous cet angle, il devient évident que pour des scénarios plus complexes, les usines doivent être à l’abri des balles et faciles à manipuler, du moins pour ne pas déranger votre ordinateur TDD..

Émuler des associations de modèles via Factory Girl est relativement simple, je dirais. Cela en soi est assez incroyable dans mon esprit. Atteindre un niveau élevé de facilité et de commodité pour la construction d’ensembles de données complexes fait de la pratique du TDD une évidence et une efficacité accrue..

Le nouveau Q a des compétences en piratage informatique et doit posséder un ordinateur décent, non? Dans ce cas, vous avez un Ordinateur classe et ses instances appartiennent à des instances du Intendant classe. Facile, droit?

FactoryGirl.define do factory: quartermaster do nommer 'Q' compétences 'Inventer des trucs' fin fabrique: ordinateur faire modèle 'Custom Lenovo ThinkPad W Series' quartermaster 

Qu'en est-il de quelque chose d'un peu plus impliqué? Disons que nos espions utilisent un pistolet ça a beaucoup cartouches (balles).

cartouche de classe < ActiveRecord::Base belongs_to :gun end class Gun < ActiveRecord::Base has_many :cartridges end 
FactoryGirl.define do factory: cartouche do calibre '7.65' usine: pistolet nommer 'Walther PPK' munition '7.65mm Browning' calibre '7.65' usine: gun_with_ammo do transitient do magazine_size 10 fin après (: créer) do | gun , évaluateur | create_list (: cartouche, évaluator.magazine_size, pistolet: pistolet) fin fin fin fin 

Les rappels sont très utiles avec les associations, hein? Maintenant, vous pouvez construire une arme à feu avec ou sans munitions. Via le hash pistolet: pistolet vous avez fourni le cartouche l’usine avec les informations nécessaires pour créer l’association via le logiciel clé étrangère.

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

Si vous avez besoin d’un autre format de magazine, vous pouvez le transmettre via votre attribut transitoire.

big_magazine_gun = créer (: gun_with_ammo, magazine_size: 20) big_magazine_gun.cartridges.length # => 20 

Alors qu'en est-il des différentes stratégies de construction? N'y avait-il pas quelque chose de louche? Eh bien, voici ce dont vous devez vous rappeler: Si vous utilisez créer pour les objets associés, les deux seront sauvegardés. Alors créer (: quartermaster) va construire et sauver à la fois Q et son ThinkPad.

Je ferais mieux d'utiliser construire, alors, si je veux éviter de frapper la base de données, non? Bonne idée, mais construire ne s'appliquerait qu'à intendant dans notre exemple, les associés ordinateur serait toujours sauvé. Un peu délicat, je sais. Voici ce que vous pouvez faire si vous ne souhaitez pas enregistrer l'objet associé. Vous spécifiez la stratégie de construction dont vous avez besoin pour votre association..

FactoryGirl.define do factory: quartermaster do name 'Q' skills 'Inventing stuff' et fin usine: computer modeler l'association 'Custom Lenovo ThinkPad W Series': quartermaster, stratégie:: construction, fin, fin 

Vous nommez l’objet usine associé et transmettez un hachage avec votre stratégie de construction. Vous devez utiliser l'explicite association appeler pour que cela fonctionne. L'exemple ci-dessous ne fonctionnera pas.

usine: l'ordinateur modélise le quartier-maître de la «Lenovo ThinkPad W Series personnalisée», stratégie: 

Maintenant les deux objets utilisent construire et rien n'est enregistré dans la base de données. Nous pouvons vérifier cette hypothèse en utilisant nouvel enregistrement?, qui retourne vrai si l'instance n'a pas été persistée.

thinkpad = construire (: ordinateur) thinkpad.new_record? # => vrai thinkpad.quartermaster.new_record? # => true 

Pendant que nous y sommes, via l'explicite association appelez, vous pouvez également vous référer à différents noms d’usines et modifier les attributs à la volée.

FactoryGirl.define do factory: quartermaster do name 'Q' fin factory: computer do model association 'Custom Lenovo ThinkPad W Series': pirate informatique, fabrique:: quartermaster, compétences: 'Piratage' 

Fermons ce chapitre avec un exemple qui est polymorphe.

classe Spy < 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 'Intelligence militaire, Section 5' principal_activity 'Usine de contre-espionnage interne': misix do nomme 'Intelligence militaire, Section 6' de principal_activity 'Usine de contre-espionnage interne': mifive_spy, class: Association d'espionnage '005': usine:: mifive fin usine: misix_spy, classe: Association d'espionnage '006': usine,:: fin misix # agents MI5 mifive = créer (: mifive) mifive_spy = créer (: mifive_spy) mifive.spies << mifive_spy mifive.name # => "Renseignements militaires, Section 5" mifive_spy.name # => '005' mifive.spies.length # => 1 mifive.spies.first.name # => '005' # agents MI6 misix = créer (: misix) misix_spy_01 = create (: misix_spy, nom: '007') misix_spy_02 = create (: misix_spy) misix.spies << misix_spy_01 misix.spies << misix_spy_02 misix.name # => "Renseignements militaires, Section 6" misix.spies.length # => 2 misix_spy_01.name # => '007' misix_spy_02.name # => '006' misix.spies.first.name # => '007' 

Ne vous sentez pas mal si celle-ci a besoin d'un peu plus de temps. Je vous recommande de vous mettre au courant des associations polymorphes si vous n'êtes pas sûr de ce qui se passe ici..

Alias

Les alias de vos usines vous permettent d’exprimer davantage le contexte dans lequel vous utilisez vos objets d’usine. Il vous suffit de fournir un hachage de noms alternatifs qui décrivent mieux la relation entre les objets associés..

Disons que vous avez un :agent usine et un : law_enforcement_vehicle usine. Ne serait-il pas agréable de se référer à l'agent comme :propriétaire dans le contexte de ces voitures? Dans l'exemple ci-dessous, je l'ai comparé à un exemple sans alias.

FactoryGirl.define do factory: agent, alias: [: propriétaire] nommer 'Fox Mulder' emploi 'Chasser les mauvais types' spécial_skills 'Investigation et intelligence' factory: double_O_seven ne nommer 'James Bond': Achieva 'type' Voiture compacte '': propriétaire de l'usine: spy_car nomme 'Aston Martin DB9' type 'Voiture de sport' double_O_seven end end 

Attention!

N'oubliez pas d'ajouter un deux-points devant la fabrique aliasée (:propriétaire) lorsque vous les utilisez pour des associations dans vos usines. La documentation et de nombreux articles de blog les utilisent sans deux-points dans ces cas. Tout ce que vous obtenez est probablement un NoMethodError car il vous manque maintenant une méthode de définition pour cet alias. (Je ferais mieux d'ouvrir une demande de tirage.) La première fois que j'ai eu ce problème, cela m'a déconcerté et m'a pris un peu pour aller au-delà. N'oubliez pas de ne pas toujours faire confiance à la documentation et aux billets de blog. Bien à vous aussi, bien sûr.

Je pense que vous conviendrez que l'utilisation d'alias permet non seulement une meilleure lecture, mais vous donne également, à vous ou à la personne qui vous suit un peu plus de contexte, à propos des objets en question. Oui, vous devez utiliser le pluriel : alias aussi si vous n'avez qu'un seul alias.

Vous pouvez écrire ceci un peu différemment et beaucoup plus verbalement.

usine: agent, alias: [: mulder] ne nomme que 'Fox Mulder' emploi 'Chasseur de méchants' special_skills 'Investigation and intelligence' fin usine: law_enforcement_vehicle nomme 'Oldsmobile Achieva' genre 'Voiture compacte' association: propriétaire, usine: agent fin 

Eh bien, pas si chouette, est-ce?

Bien sûr, vous pouvez aussi utiliser ces alias pour "construire" immédiatement des objets d'usine..

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

Dans le contexte des commentaires, un :utilisateur pourrait être appelé : commentateur, dans le cas d'un :la criminalité une :utilisateur pourrait être aliasé en tant que :suspect, etc. Ce n’est pas vraiment sorcier, mais plutôt un sucre syntaxique pratique qui diminue la tentation de la duplication..

Traits

C'est l'une de mes choses préférées à propos de Factory Girl. En un mot, les traits sont des blocs de type lego pour construire vos usines et mélanger les comportements. Ce sont des listes de traits / attributs de symboles séparés par des virgules que vous souhaitez ajouter à une fabrique particulière. Elles sont également définies dans le (s) fichier (s) de votre usine..

Dans mon esprit, trait est la fonction la plus puissante et la plus pratique pour garder vos données d’usine au sec tout en étant expressives. Il vous permet de regrouper des groupes d'attributs, de leur attribuer des noms distincts et de les réutiliser à votre guise. Tu te souviens quand je t'ai exhorté à définir des objets d'usine nus? Traits vous aidera à atteindre exactement ce but sans sacrifier la commodité.

FactoryGirl.define do factory: spy_car ne modèle 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat trait vrai: sous-marin eject_seat faux 'résistant à l'eau' 100 m 'submarine_capabilities true air_independent_propulsion true end '12' machine_gun true rate_of_fire '1 500 tr / min' tank_armour trait final vrai: masqué active_camouflage radar_signature radar 'signature réduite' moteur 'silencieux' réduit trait: night_vision do infrarared_sensors vrai head_up_display vrai bout final 

Comme vous pouvez le constater, si vous souhaitez modifier certains attributs répartis sur plusieurs objets, vous pouvez le faire maintenant dans un emplacement central. Aucune opération à la carabine n'est nécessaire. Gérer l'état via des traits ne pourrait pas être plus pratique.

Avec cette configuration, vous pouvez construire des voitures espions assez élaborées en mélangeant les différents ensembles d'attributs comme bon vous semble, sans rien dupliquer en créant toutes sortes de nouvelles usines qui tiennent compte de toutes les options dont vous avez besoin..

invisible_spy_car = create (: spy_car,: cloaked,: night_vision) diving_spy_car = create (: spy_car,: sous-marin,: sous-marin): tank_spy_car = create (: spy_car,: armeisé,: night_vision) 

Vous pouvez utiliser des traits avec créer, construire, build_stubbed et attributs_pour. Si Q devient intelligent, vous pouvez également remplacer des attributs individuels simultanément en transmettant un hachage..

build (: spy_car,: submarine, ejection_seat: true) 

Pour les combinaisons de traits qui se produisent très fréquemment sur une usine particulière, vous pouvez également créer des usines enfants avec des noms qui représentent le mieux les différentes combinaisons d’ensembles de données. De cette façon, vous ne regroupez leurs traits qu'une seule fois, contrairement à tout le temps lorsque vous créez des données de test..

FactoryGir.define do factory: spy_car ne modèle 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat trait vrai: sous-marin fait… trait fin: fait avec une arme… fin trait: fait avec manteau… fin trait: avec vue nocturne… fin fin usine: invisible_spy_car, traits: [: cloaked,: night_vision] usine: diving_spy_car, traits: [: sous-marin,: camouflé] usine: tank_spy_car, traits: [: avec une arme à feu,: nightvision] usine: ultimate_spy_car, traits: [: un manteau ,: vision nocturne,: sous-marin,: armé] fin 

Cela vous permet de créer ces objets de manière plus concise et plus lisible..

build_stubbed (: invisible_spy_car) create (: ultimate_spy_car) 

Au lieu de:

build_stubbed (: spy_car,: cloaked,: night_vision) crée (: spy_car,: cloaked,: night_vision,: sous-marin,: avec une arme) 

Lit beaucoup mieux, non? Surtout quand aucun nom de variable n'est impliqué.

Vous pouvez même réutiliser des traits en tant qu'attributs sur d'autres traits et usines. Si vous définissez les mêmes attributs pour plusieurs traits, le dernier défini sera prioritaire, bien sûr..

FactoryGirl.define do factory: spy_car ne modèle 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat trait vrai: sous-marin fait… trait fin: fait avec une arme… fin trait: fait avec un manteau… fait trait avec nuit… trait fin: mobile_surveillance faire night_vision signal_detector true signal_analyseur true wifi_war_driver true licence_plate_reader true mini_drone true fin fin usine: ultimate_spy_car, parent:: spy_car do car_plane vrai sous-marin armeé mobile_surveillance fin fin 

Faites attention au surveillance_mobile trait, qui réutilise le masqué et vision nocturne traits-essentiellement comme un attribut. Également ultimate_spy_car usine, que je sépare de la spy_car définition d'usine pour le plaisir cette fois, réutilise tous les traits plus un attribut supplémentaire qui le fait voler aussi. Pure magie de film - ou peut-être devrais-je dire magie Factory Girl.

créer une liste et liste de construction peut également utiliser des traits. Le deuxième paramètre doit être le nombre d'instances d'usine que vous souhaitez.

create_list (: spy_car, 3,: night_vision) build_list (: spy_car, 4,: sous-marin,: cloaked) 

Ce ne serait pas cool d'utiliser des associations avec des traits? Bien sûr, vous pouvez parfaitement intégrer les rappels et les associations dans des traits. Duh!

FactoryGirl.define do factory: cartouche do kind 'pistolet calliber' calibre '7.65' projectile 'plomb' fabrique de pistolets: golden_cartridge do projectile association 'Gold': pistolet,: fin doré usine: pistolet nommer munition 'Walther PPK' Calibre '7.65mm Browning' 7.65 'transitoire do magazine_size 10 trait fin: golden do nom munitions' Custom Lazar ''23 - carat gold bullet' trait fin: with_ammo do après (: créer) faire | gun, évaluateur | create_list (: cartouche, évaluateur.magazine_size, pistolet: pistolet) trait de fin d'extrémité: with_golden_ammo do after (: create) do | golden_gun, évaluateur | create_list (: golden_cartridge, evaluator.magazine_size, gun: golden_gun) fin fin fin fin 

Comment les utiliser devrait être ennuyeux maintenant.

 cartouche = créer (: cartouche) cartouche.projectile # => 'Plomb' cartouche.gun.name # => 'Walther PPK' cartouche.gun.ammunition # => '7.65mm Browning' cartouche.gun.caliber # => ' 7.65 'golden_cartridge = create (: golden_cartridge) golden_cartridge.projectile # =>' Or 'golden_cartridge.gun.name # =>' Custom Lazar 'golden_cartridge.gun.ammunition # => '23 - Bille en or à carreaux' 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' gun_with_ammo.cartridges.length # => 10 gun_with_ammo.cartridges. first.projectile # => 'Lead' gun_with_ammo.cartridges.first.caliber # => '7.65' golden_gun_with_golden_ammo = créer (: gun,: golden, avec_golden_ammo) golden_gun_with_golden_ammo.name # = '' > Balle en or à 24 carats golden_gun_with_golden_ammo.cartridges.first.caliber # => '7.65' 

Dernières pensées

Derniers mots de sagesse: Le changement est votre compagnon constant. Il faut constamment modifier les attributs ou les types de données. Les décisions de conception comme celles-ci évoluent. Les traits faciliteront la tâche et vous aideront à gérer vos ensembles de données..

Imaginez si vous aviez utilisé un hachage d’options pour l’instanciation et que cette exigence avait totalement changé. Combien de places potentielles dans vos tests pourraient casser et nécessiteront maintenant votre attention? Directement, trait est un outil très efficace pour éliminer les doublons dans votre suite de tests. Mais avec toute cette commodité, ne soyez pas paresseux et oubliez vos tests unitaires sur les colonnes représentées par vos traits! De cette façon, vous leur accordez le même soin que les attributs de base nécessaires pour les objets valides..

Dans Factory Girl, il y a un peu plus à découvrir et je suis convaincu que vous êtes maintenant plus que bien équipé pour assembler les éléments lorsque vous en avez besoin. Amusez-vous à jouer avec ce joyau. J'espère que vos habitudes TDD en bénéficieront.