Fabrica de fete 201

Ce veți crea

Al doilea articol despre acest obiect popular și util Ruby se ocupă de câteva subiecte mai nuanțate, pe care începătorii nu trebuie neapărat să se preocupe imediat după ce au început. Din nou, am facut tot ce mi-a stat in putinta pentru a-mi pastra accesul la inceput si pentru a explica fiecare bucata de oameni lingo noi la TDD (Test-Driven Development).

Subiecte

  • Dependente atribute
  • Atribute tranzitorii
  • Lazy atribute
  • Modificarea fabricilor
  • Reapelări
  • Asociațiile
  • Pseudonime
  • trasaturi

Dependente atribute

Dacă aveți nevoie să utilizați valori de atribute pentru a compune alte atribute ale fabricii în zbor, Factory Girl v-ați acoperit. Trebuie doar să înfășurați valoarea atributului într-un bloc și să interpolați atributele de care aveți nevoie. Aceste blocuri au acces la un evaluator-care le este oferită - și care la rândul său are acces la alte atribute, chiar și cele tranzitorii.

FactoryGirl.define fabrică: supervillain do nume "Karl Stromberg" pasiune "biologie marină" ambiție "extincție umană" motivație "salva profilul oceanelor " # name are o pasiune pentru # passion  prin ambiție. end-end villain = create (: supervillain) villain.profile # => "Karl Stromberg are o pasiune pentru biologia marină și își propune să salveze oceanele prin dispariția omului. 

Atribute tranzitorii

Cred că este corect să le numim atribute false. Aceste atribute virtuale vă permit, de asemenea, să transmiteți opțiuni suplimentare când construiți instanțele din fabrică - printr-un hash desigur. Instanța însăși nu va fi afectată de acestea, deoarece aceste atribute nu vor fi setate pe obiectul dvs. din fabrică. Pe de altă parte, Factory Girl tratează atribute tranzitorii la fel ca cele reale.

Dacă utilizați attributes_for, acestea nu vor apărea totuși. Atributele independente și callback-urile au acces la aceste atribute false în interiorul fabricii. În ansamblu, acestea reprezintă o altă strategie pentru a vă ține fabricile DRY.

FactoryGirl.define face fabrică: supervillain do transient do megalomaniac false proprietar de pisică false nume final "Karl Stromberg" pasiune "biologie marină" ambiție "extincție umană" motivație "construirea unei civilizații subacvatice # " și salvarea lumii "dacă megalomaniac" Profil "Insane business tycoon # " - prieteni cu Blofeld "if cat_owner" end end villain = create (: supervillain) villain.profile # => "cat_friendly_villain = create (: supervillain, cat_owner: true) cat_friendly_villain.profile # =>" Construieste o civilizatie subacvatica si salvând lumea " 

Exemplul de mai sus se dovedește a fi puțin mai uscat, deoarece nu era nevoie să se creeze fabrici separate pentru supervilini care să salveze lumea sau să fie prieteni cu Blofeld respectiv. Atributele tranzitorii vă oferă flexibilitatea de a face tot felul de ajustări și de a evita crearea unei mulțimi de fabrici care sunt tot atât de asemănătoare.

Lazy Attributes

Atributele "Normal" din Factory Factory sunt evaluate când se definește fabrica. De obicei, furnizați valori statice ca parametri pentru metodele cu același nume ca atributele dvs. Dacă doriți să întârziați evaluarea până la ultimul moment posibil - când instanța devine instanțiată - va trebui să vă alimentați valorile prin intermediul unui bloc de cod. Asociații și valori create dinamic din obiecte cum ar fi DateTime obiectele vor fi clienții cei mai frecvenți pentru tratamentul leneș.

FactoryGirl.define a face fabrica: exploding_device face tranzitoriu numărătoarea_dezonată_secundă 10 * 60 time_of_explosion Time.now + countdown_seconds end time_of_explosion "Exploding în # countdown_seconds secunde # time_of_explosion.strftime (" la% I:% M% p ")  " end end ticking_device = crea (: exploding_device) ticking_device.time_of_explosion # =>" Explozie în 600 de secunde la 23:53 " 

Modificarea fabricilor

Acesta nu este probabil un caz de utilizare pe care îl veți întâlni în fiecare zi, dar uneori puteți moșteni fabrici de la alți dezvoltatori și doriți să le schimbați - în cazul în care utilizați o bijuterie TDD'd, de exemplu. Dacă simțiți nevoia de a optimiza aceste fabrici moștenite pentru a se potrivi mai bine scenariilor dvs. de testare specifice, le puteți modifica fără a crea altele noi sau folosind moștenirea.

Faceți asta prin intermediul FactoryGirl.modify, și trebuie să fie în afara acestui anumit FactoryGirl.define bloc pe care doriți să îl modificați. Ce nu puteți face este să modificați secvenţă sau trăsătură-puteți suprascrie atributele definite prin trăsătură deşi. Redirecționările returnate din fabrica "originală" nu vor fi suprimate. Callback-ul în telefonul tău Factory.modify bloc va fi doar rula ca următorul în linie.

FactoryGirl.define a face fabrica: spion face numele "Marty McSpy" abilități "Spionaj și infiltrare" deployment_status "Pregătirea misiunii" sfârșitul sfârșitului FactoryGirl.modify do sequence: mission_deployment do | number | "Misiunea # număr la # DateTime.now.to_formatted_s (: scurtă)" fabrica finală: spion face name "CQC și" favorit_weapon "poker lui Walter PPK 'body_count' Clasificat 'favorite_car' Aston Martin DB9 "implementare generate (: mission_deployment) end end 

În exemplul de mai sus, am avut nevoie de spionii noștri pentru a fi un pic mai "mai sofisticați" și de a folosi un mecanism mai bun pentru a gestiona desfășurarea. Am văzut exemple în care autorii de bijuterii trebuiau să se ocupe de timp diferit și unde a fost util să modifice obiectele din fabrică prin simpla depunere a lucrurilor pe care trebuie să le modificați.

Reapelări

Comenzile de returnare vă permit să injectați un anumit cod la diferite momente din ciclul de viață al unui obiect asemănător Salvați, after_save, before_validation si asa mai departe. Rails, de exemplu, oferă o grămadă de ele și face destul de ușor pentru începători să abuzeze de această putere.

Rețineți că apelurile care nu sunt legate de persistența obiectelor sunt un model anti-model cunoscut și este un sfat bun pentru a nu trece linia respectivă. De exemplu, s-ar putea să fie convenabil să utilizați un apel invers după ce ați instanțiat ceva ca un utilizator pentru a trimite e-mailuri sau pentru a procesa o anumită ordine, dar aceste tipuri de lucruri invită bug-uri și creează legături inutile greu de refăcut. Poate că acesta a fost unul dintre motivele pentru care Factory Girl "numai" vă oferă cinci opțiuni de apel invers pentru a juca cu:

  • înainte de a (: a crea) execută un bloc de cod înainte de salvarea instanței din fabrică. Activat când utilizați creați (: some_object).
  • după (: a crea) execută un bloc de cod după salvarea instanței din fabrică. Activat când utilizați creați (: some_object).
  • după (: build) execută un bloc de cod după ce obiectul dvs. din fabrică a fost construit în memorie. Activat când utilizați ambele construi (: some_object) și creați (: some_object).
  • după (: stub) execută un bloc de cod după ce fabrica dvs. a creat un obiect stubbed. Activat când utilizați build_stubbed (: some_object).
  • personalizate (: your_custom_callback) execută un apel inversat personalizat, fără a fi nevoie să prependați inainte de sau după.
FactoryGirl.define face fabrică: misiunea face obiectivul "Stopping the bad dude" cu condiția "mini submarin și pistol rechin" provided_gadgets după (: build) assign_support_analyst end end 

Atenţie!

Rețineți că pentru toate opțiunile de apel invers, în interiorul blocurilor de apel invers, veți avea acces la o instanță a fabricii prin intermediul unui parametru de blocare. Acest lucru va veni la îndemână din când în când, mai ales cu asociații.

FactoryGirl.define face fabrică: double_agent face după (: stub) | double_agent | assign_new_identity (double_agent) end end 

Mai jos, un ninja are la dispoziție o grămadă de stele uriașe de aruncare (shuriken). Din moment ce ai ninja obiect în apel invers, puteți să atribuiți cu ușurință steai care aruncă să aparțină Ninja. Luați o privire la secțiunea despre asociațiile dacă exemplul respectiv vă va lăsa cu câteva semne de întrebare.

FactoryGirl.define a face fabrica: ninja face numele "Ra's al Ghul" fabrica: ninja_with_shuriken face tranzitoriu number_of_shuriken 10 sfarsit dupa (: create) nu | ninja, evaluator | create_list (: shuriken, evaluator.number_of_shuriken, ninja: ninja) sfârșitul sfârșitul sfârșitul fabrică: shuriken face numele "Hira-shuriken" number_of_spikes "patru" ninja sfarsit sfârșitul ninja = crea (: ninja) ninja.shurikens.length # = create (: ninja_with_shuriken) ninja.shurikens.length # => 10 ninja = create (: ninja_with_shuriken, numărul_șurubului: 20) ninja.shurikens.length # => 20 

De asemenea, prin obiectul evaluatorului aveți acces la atributele tranzitorii. Acest lucru vă oferă opțiunea de a transmite informații suplimentare atunci când creați obiecte din fabrică și trebuie să le modificați în zbor. Aceasta vă oferă toată flexibilitatea necesară pentru a juca cu asociații și a scrie date de testare expresive.

Dacă găsiți necesitatea de a avea mai multe apeluri înapoi în fabrică, Factory Girl nu este în picioare în calea ta - chiar și cele de tip multiplu. Firește, ordinea execuției este de sus în jos.

FactoryGirl.define fabrică: henchman face numele "Mr. Hinx după (: crea) | henchman | henchman.send_on_kill_mission după (: create) send_cleaner end end 
FactoryGirl.define a face fabrica: bond_girl face numele "Lucia Sciarra" după (: build) | bond_girl | bond_girl.hide_secret_documents după (: creați) close_hidden_safe_compartment end end 

Diavolul este în detaliu, desigur. Dacă utilizați creați (: some_object), ambii după (: build) și după (: a crea) apelurile vor fi executate.

Strategiile de construcție multiple pot fi grupate pentru a executa același apel invers.

FactoryGirl.define a face fabrica: spion face numele "Marty McFly" după (: stub,: build) | spy | spy.assign_new_mission sfârșitul final 

Nu în ultimul rând, puteți chiar să configurați ceva de genul apeluri "globale" care înlocuiesc apelurile de apel pentru toate fabricile - cel puțin în acel fișier dacă le-ați separat în mai multe fișiere din fabrică.

fabrici / gun.rb

FactoryGirl.define face înainte (: stub,: build,: create) | object | numarul fabricatiei: spy_gun face numele 'Walther PPK' muniție '7.65mm Browning' asociație: fabrica de proprietar: golden_gun face numele 'Custom Lazar' muniție '24 -carat gold bullet 'după (: create) | golden_gun | numerele de caractere terminale 

Atenţie!

Dacă folosiți moștenirea pentru a compune fabrici de copii, apelurile de la părinți vor fi moștenite, de asemenea.

Ultima Mile

Să le aducem împreună în următoarele secțiuni despre asociațiile și trăsături-Da, de asemenea, am furișat alias pentru că a fost cel mai bun loc fără să sară peste tot. Dacă ați acordat atenție și ați amintit lucrurile de la primul articol, totul ar trebui să cadă destul de bine acum.

Asociațiile

Asociațiile sunt esențiale pentru fiecare aplicație web cu respect față de sine, care are o mică complexitate. Un post care aparține unui utilizator, o listă care are multe evaluări și așa mai departe sunt dezvoltatorii de pâine și unt au pentru micul dejun în orice zi a săptămânii. Din această perspectivă, devine evident că pentru scenarii mai complexe, fabricile trebuie să fie rezistente la bullet și ușor de manevrat - cel puțin pentru a nu mizeria cu mojo TDD.

Asamblarea asociațiilor de modele prin Factory Girl este relativ simplă, aș spune. Acest lucru este în sine uimitor în mintea mea. Realizarea unui nivel înalt de ușurință și comoditate pentru construirea seturilor de date complexe face ca practica TDD să devină un mod de a-și îmbunătăți calitatea și a fi mult mai eficientă.

Noul Q are abilități de hacker și trebuie să dețină un calculator decent, nu? În acest caz, aveți a Calculator clasa și instanțele sale aparțin instanțelor Intendent clasă. Ușor, corect?

FactoryGirl.define a face fabrica: quartermaster face aptitudini Q "Inventarea lucruri" sfârșitul fabrica: computerul face modelul "Custom Lenovo ThinkPad W Series" capăt sfârșitul sfârșitul 

Dar ceva mai implicat? Să spunem că spionii noștri folosesc a armă care are_many cartușe (gloanțe).

clasă Cartridge < ActiveRecord::Base belongs_to :gun end class Gun < ActiveRecord::Base has_many :cartridges end 
FactoryGirl.define fabrică: cartuș de calibru '7.65' fabrica finală pistol: pistol face numele "Walther PPK" muniție "7.65mm Browning" calibru 7.65 "fabrică: gun_with_ammo a face tranzitoriu do magazine_size 10 sfârșitul după (: crea) , evaluator | create_list (: cartuș, evaluator.magazine_size, pistol: pistol) capăt capăt sfârșit sfârșit 

Întoarcerile de apel vin destul de la îndemână cu asociațiile, nu? Acum puteți construi un pistol cu ​​sau fără muniție. Prin hash pistol: pistol ați furnizat cartuş fabrică cu informațiile necesare pentru a crea asocierea prin cheie externă.

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

Dacă aveți nevoie de o altă dimensiune a revistei, puteți să o transmiteți prin intermediul dvs. caracter transient.

big_magazine_gun = creați (: gun_with_ammo, magazine_size: 20) big_magazine_gun.cartridges.length # => 20 

Deci, cum rămâne cu strategiile de construcție diferite? Nu era ceva încrezător? Ei bine, iată ce trebuie să vă amintiți: dacă utilizați crea pentru obiectele asociate, ambele vor fi salvate. Asa de creați (: intendent) va construi și salva atât Q, cât și ThinkPad-ul său.

Mai bine folosesc construi, atunci, dacă vreau să evit să apăr baze de date, nu-i așa? Bună idee, dar construi se aplică numai pentru intendent în exemplul nostru - asociat calculator ar fi salvat încă. Un pic cam înșelător, știu. Iată ce puteți face dacă trebuie să evitați salvarea obiectului asociat - specificați strategia de construire de care aveți nevoie pentru asocierea dvs..

FactoryGirl.define a face fabrica: quartermaster face aptitudini Q "Inventarea lucrurilor" fabrica finala: computerul face modelul "Custom Lenovo ThinkPad W Series" asociere: quartermaster, strategie:: build end end 

Denumiți obiectul fabrica asociat și treceți într-un hash cu strategia dvs. de construire. Trebuie să utilizați funcția explicită asociere cereți ca acest lucru să funcționeze. Exemplul de mai jos nu va funcționa.

fabrică: modelul computerului "personalizat Lenovo ThinkPad W Series", strategia:: construi sfârșit 

Acum folosiți ambele obiecte construi și nimic nu se salvează în baza de date. Putem verifica această ipoteză prin utilizarea un nou record?, care se întoarce Adevărat dacă instanța nu a fost persistentă.

thinkpad = construi (: calculator) thinkpad.new_record? # => true thinkpad.quartermaster.new_record? # => true 

În timp ce suntem la el, prin explicită asociere de asemenea, puteți să vă referiți la diferite nume ale fabricilor și să schimbați atributele în zbor.

FactoryGirl.define a face fabrica: quartermaster face numele "Q" sfârșitul fabrică: computer face modelul "personalizate Lenovo ThinkPad W Series" asociere: hacker, fabrică:: quartermaster, competențe: "Hacking" 

Să închidem acest capitol cu ​​un exemplu care este polimorfă.

clasa 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 fabrică: numele mifive face "Inteligența militară, secțiunea 5" principala activitate "Fabrică de cont contra inteligenței interne": misix face name "Inteligența militară, secțiunea 6" principală activitate " Spy face numele asociației "005": spyable, factory:: fabrica finală mifive: misix_spy, clasa: Spy do name '006' asociere: spyable, factory:: misix end end # MI5 agenți mifive = create (: mifive) mifive_spy = (: mifive_spy) mifive.spies << mifive_spy mifive.name # => "Inteligența militară, secțiunea 5" mifive_spy.name # => '005' mifive.spies.length # => 1 mifive.spies.first.name # => '005' # MI6 agenți misix = create (: misix) misix_spy_01 = creați (: misix_spy, nume: '007') misix_spy_02 = creați (: misix_spy) misix.spies << misix_spy_01 misix.spies << misix_spy_02 misix.name # => "Inteligența militară, secțiunea 6" misix.spies.length # => 2 misix_spy_01.name # => '007' misix_spy_02.name # => '006' misix.spies.first.name # => 

Nu vă simțiți rău dacă acest lucru are nevoie de un pic mai mult timp pentru a vă scufunda. Vă recomandăm să căutați pe Asociațiile Polimorfe dacă nu sunteți sigur ce se întâmplă aici.

Pseudonime

Aliasurile pentru fabricile dvs. vă permit să fiți mai expresivi cu privire la contextul în care folosiți obiectele din fabrică. Trebuie doar să furnizați un hash cu nume alternative care descriu mai bine relația dintre obiectele asociate.

Să presupunem că aveți un :agent fabrică și a : law_enforcement_vehicle fabrică. Nu ar fi frumos să te referi la agent ca :proprietar în contextul acestor mașini? În exemplul de mai jos, l-am contrastat cu un exemplu fără un pseudonim.

FactoryGirl.define fabrică: agent, nume: [: proprietar] face numele "Fox Mulder" locul de muncă "Chasing boys bad" special_skills "Fabrica de investigație și inteligență": double_O_seven face numele "James Bond" sfârșitul fabrică finală: law_enforcement_vehicle face numele "Oldsmobile Achieva "tip" Masina compacta ": proprietar capat fabrica: spy_car face numele" Aston Martin DB9 "tip" masina sport "double_O_seven end end 

Atenţie!

Nu uitați să adăugați un colon în fața fabricii aliate (:proprietar) când le folosiți pentru asociații din fabricile dvs. Documentația și multe postări pe blog le utilizează fără colonii în aceste cazuri. Tot ce este posibil este probabil a NoMethodError deoarece lipsește o metodă de setare pentru acel alias acum. (Ar fi mai bine să deschid o cerere de tragere.) Prima dată când am intrat în asta, ma deranjat și mi-a luat puțin pentru a trece de ea. Amintiți-vă uneori, în mod selectiv, neîncrederea documentelor și postărilor pe blog. Cu adevărat, bineînțeles.

Cred că veți fi de acord că folosirea de pseudonime nu numai că citește mai bine, ci vă oferă și tu sau persoana care vine după tine un context mai mult despre obiectele în cauză. Da, trebuie să folosiți pluralul : pseudonime de asemenea, dacă aveți doar un singur pseudonim.

Puteți scrie și acest lucru diferit, mult mai mult.

fabrică: agent, pseudonime: [: mulder] face numele de "Fox Mulder" de locuri de muncă "Chasing dudes bad" special_skills "Fabrica de investigare și inteligență" sfârșitul fabrică: law_enforcement_vehicle numele "Oldsmobile Achieva" asociație "Compact auto" sfârșitul agentului 

Ei bine, nu așa de îngrijit, nu-i așa??

Desigur, puteți folosi aceste pseudonime și pentru a "construi" imediat obiecte din fabrică.

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

În contextul comentariilor, a :utilizator ar putea fi denumite :comentator, în cazul a : crima A :utilizator ar putea fi alias ca a :suspect, si asa mai departe. Nu este știința rachetelor cu adevărat - mai mult ca un sac de sintactică convenabil, care scade tentațiile de duplicare.

trasaturi

Acesta este unul dintre lucrurile mele preferate despre Factory Girl. Pe scurt, trăsăturile sunt blocuri lego-tip pentru a construi fabricile și a le amesteca în comportament. Acestea sunt liste separate prin virgulă cu trăsăturile / atributele de simbol pe care doriți să le adăugați la o anumită fabrică și sunt, de asemenea, definite în fișierele (fișierele) fabricilor dvs..

In mintea mea, trăsătură este cea mai puternică și mai convenabilă funcție pentru păstrarea datelor din fabrică DRY în timp ce este expresivă în același timp. Vă permite să îmbinați grupuri de atribute împreună, să le dați nume separate și să le refolosiți oriunde doriți. Amintiți-vă când v-am îndemnat să definiți obiecte fabricate din oase goale? Trăsăturile vă vor ajuta să obțineți exact acest lucru fără a sacrifica orice confort.

FactoryGirl.define a face fabrica: spy_car face modelul 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat adevărat trăsătură: submarin ejection_seat false water_resistant '100 m' submarine_capabilities true air_independent_propulsion adevărat trăsătură finală: rachete rachete rachete true number_of_rockets '12' machine_gun true rate_of_fire '1.500 RPM' tank_armour adevărat caracteristică finală: cloaked face active_camouflage true radar_signature 'redus' motor 'silențios' trăsătură finală: night_vision do infrared_sensors true heads_up_display true end end end 

După cum puteți vedea, dacă vreți să schimbați unele atribute care sunt răspândite pe mai multe obiecte, puteți face acest lucru într-un singur loc central. Nu este nevoie de o operație cu pușcă. Gestionarea statului prin trăsături nu ar putea fi mai convenabilă.

Cu această configurație puteți construi mașini de spionaj destul de elaborate prin amestecarea diferitelor pachete de atribute, oricum doriți - fără a duplica nimic prin crearea a tot felul de fabrici noi care să răspundă pentru toate opțiunile de care aveți nevoie.

invizible_spy_car = creare (: spy_car,: cloaked,: night_vision) diving_spy_car = creare (: spy_car,: submarin,: cloaked) tank_spy_car = creare (: spy_car,: weaponized,: night_vision) 

Aveți posibilitatea să utilizați trăsăturile cu crea, construi, build_stubbed și attributes_for. Dacă Q devine inteligent, puteți, de asemenea, să înlocuiți atributele individuale simultan prin trecerea într-un hash.

construi (: spy_car,: submarin, ejection_seat: true) 

Pentru combinațiile de trăsături care apar foarte frecvent într-o anumită fabrică, puteți crea, de asemenea, fabrici de copii cu nume care reprezintă cele mai bune combinații de seturi de date. În acest fel le-ați legat caracteristicile lor o singură dată, spre deosebire de tot timpul când creați datele de testare.

FactoryGir.define a face fabrica: spy_car a face modelul 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat trăsătură adevărată: submarinul nu ... trăsătură finală: armatizată nu ... trăsătură finală: cloaked ... trăsătură finală: night_vision do ... end fabrica: invisible_spy_car, trasaturi: [: cloaked,: night_vision] fabrică: diving_spy_car, trasaturi: [: submarin,: cloaked] fabrică: tank_spy_car, trasaturi: [: weaponized,: night_vision] fabrică: ultimate_spy_car, traits: [: cloaked ,: night_vision,: submarin,: weaponized] end 

Acest lucru vă permite să creați aceste obiecte mai concis, și este mai ușor de citit.

build_stubbed (: invisible_spy_car) creați (: ultimate_spy_car) 

In loc de:

build_stubbed (: spy_car,: cloaked,: night_vision) crea (: spy_car,: cloaked,: night_vision,: submarine,: weaponized) 

Citește mult mai bine, nu? Mai ales atunci când nu sunt implicate nume de variabile.

Puteți chiar reutiliza trăsăturile ca atribute ale altor trăsături și fabrici. Dacă definiți aceleași atribute pentru mai multe trăsături, ultimul definit are prioritate, desigur.

FactoryGirl.define a face fabrica: spy_car a face modelul 'Aston Martin DB9' top_speed '295 km / h' build_date '2015' ejection_seat trăsătură adevărată: submarinul nu ... trăsătură finală: armatizată nu ... trăsătură finală: cloaked ... trăsătură finală: night_vision do ... trăsătură finală: mobile_surveillance face cloaked night_vision signal_detector true signal_analyzer true wifi_war_driver true license_plate_reader true mini_drone adevărat end end fabrica: ultimate_spy_car, părinte:: spy_car do car_plane true submarine weaponized mobile_surveillance end end 

Fiți atenți la mobile_surveillance trait, care reutilizează camuflat și vedere nocturnă trăsături - în principiu ca un atribut. De asemenea ultimate_spy_car fabrică, pe care am separat-o din spy_car definiția fabricii pentru distracție de data aceasta, reutilizează toate trăsăturile, plus un atribut suplimentar care o face să zboare prea. Film magie pură - sau poate ar trebui să spun Fată Girl magic.

create_list și build_list pot folosi și trăsăturile. Al doilea parametru trebuie să fie numărul de instanțe din fabrică dorite.

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

Nu ar fi minunat să folosiți asociații cu trăsături? Desigur, puteți împacheta apeluri și asociații cu trăsături în trăsături. zău!

FactoryGirl.define fabrică: cartuș de tip "muniție pistol muniție calibru mic" calibru 7.65 "proiectil" Fabrică arma de plumb: golden_cartridge nu proiectil asociație "aur": arma,: sfârșitul de aur fabrica finală: arma face numele "Walther PPK" muniție '7,65mm calibru de Browning' 7,65 'tranzitoriu do magazine_size 10 trăsătură finală: numele de aur face' muniția Lazar personalizat '23 -caratul de aur glont 'trăsătură finală: with_ammo face după (: crea) do | gun, evaluator | create_list (: cartuș, evaluator.magazine_size, pistol: pistol) capăt final: cu_golden_ammo face după (: crea) do | golden_gun, evaluator | create_list (: golden_cartridge, evaluator.magazine_size, pistol: golden_gun) end end end end 

Cum să le folosiți trebuie să fie plictisitoare până acum.

 cartuș = cartuș = cartuș = cartuș = cartuș = cartografiere cartuș = 7.65 'golden_cartridge = creare (: golden_cartridge) golden_cartridge.gro.calibre # =>' golden_cartridge.gun.caliber '=>' # => '7.65' gun_with_ammo = crea (: arma:: 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 # => 'plumb' gun_with_ammo.cartridges.first.caliber # => '7.65' golden_gun_with_golden_ammo = a crea (: pistol,: de aur,: with_golden_ammo) golden_gun_with_golden_ammo.name # => 'personalizat Lazar golden_gun_with_golden_ammo.ammunition # = > '24 -carat gold bullet 'golden_gun_with_golden_ammo.cartridges.length # => 10 golden_gun_with_golden_ammo.cartridges.first.projectile # =>' Aur ' golden_gun_with_golden_ammo.cartridges.first.caliber # => '7.65' 

Gândurile finale

Ultimele cuvinte ale înțelepciunii: Schimbarea este partenerul tău constant - trebuie să schimbi atributele sau tipurile de date care se întâmplă tot timpul. Deciziile de proiectare ca acestea evoluează. Trăsăturile vor ușura durerea cu asta și vă vor ajuta să gestionați seturile de date.

Imaginați-vă dacă ați folosit o opțiune hash pentru instanțiere și această cerință a fost total schimbată. Câte locuri potențiale din testele tale ar putea să se întrerupă și acum vor avea nevoie de atenție? Drept în sus, trăsătură este un instrument foarte eficient pentru eliminarea duplicării în suita dvs. de testare. Dar cu tot confortul, nu fi leneș și uitați testele unității pe coloanele care sunt reprezentate de trăsăturile voastre! Astfel, le dai aceleasi ingrijiri ca atributele oaselor goale necesare obiectelor valabile.

Există un pic mai mult de descoperit în Factory Girl și sunt convins că sunteți acum mai mult decât bine pregătit pentru a pune piesele împreună atunci când aveți nevoie de ele. Bucurați-vă de joc cu această bijuterie. Sper că obiceiurile TDD vor beneficia de ea.

Cod