Active Record The Rails Database Bridge

Om in het verleden een webtoepassing te bouwen, had u de vaardigheden nodig om in uw bedrijfslogica en uw databasetaal te coderen. Meer recentelijk neigen back-end frameworks echter naar het gebruik van Object-Relational Mapping (ORM); dit is een techniek waarmee u uw database kunt beheren in de zakelijke logische taal waarmee u het meest vertrouwd bent.

Rails gebruikt een ORM in de vorm van Active Record. In deze zelfstudie duiken we in Active Record en kijken we wat het voor ons kan doen!


Wat een actief record is, precies

Zoals ik al zei, Active Record is een ORM. Dit betekent dat het een laag van Ruby-code is die tussen uw database en uw logische code loopt. Wanneer u wijzigingen in de database moet aanbrengen, schrijft u de Ruby-code en voert u vervolgens migraties uit, die we binnenkort zullen beoordelen. Deze migraties maken de feitelijke wijzigingen in de database. Het leuke is dat het niet uitmaakt welke database je gebruikt: Rails kunnen vrijwel alles aan. Rails gebruikt bijvoorbeeld SQLite lokaal tijdens het ontwikkelen. Laten we echter stellen dat u werkt aan Heroku, die PostreSQL gebruikt. Het enige wat je hoeft te doen is dit aan je toevoegen Gemfile:

 groep: productie doe edel 'pg' einde

Nu, wanneer u implementeert, zal Heroku diezelfde migraties uitvoeren (met behulp van de PostgreSQL-adapter). Dezelfde code, andere database, wat best cool is, naar mijn mening.

Dus dat is wat Active Record is; laten we dieper graven en kijken hoe het allemaal werkt.


Ermee beginnen

Hoewel het technisch mogelijk is om Active Record buiten een Rails-app te gebruiken, zult u het negen keer op tien gebruiken binnen een Rails-app, dus dat is wat we hier zullen doen. Ik gebruik Rails 3.2.12, de nieuwste versie terwijl ik dit typ. Als je dat hebt geïnstalleerd, kun je beginnen met het maken van een nieuwe Rails-app.

 rails nieuwe myapp cd myapp

Nu kunnen we beginnen met het maken van een model.


Modellen en migraties maken

Zoals je zou verwachten, omdat Active Record samenwerkt met de database, is het de M in MVC van Rails: modellen. Vanaf de opdrachtregel maken we een model voor bijvoorbeeld een persoon. Eigenlijk, de rails genereren opdracht is vrij flexibel: alle volgende opdrachten werken:

 rails genereren model Persoon rails g model Persoon rails g model Persoon first_name last_name age: integer

De eerste twee regels hier doen hetzelfde; rails g is gewoon een snelkoppeling voor rails genereren. De derde geeft Rails een beetje meer informatie, zodat het wat meer werk voor ons kan doen. We zeggen dat we willen dat dit model drie velden heeft: Voornaam, achternaam, en leeftijd. Voor Voornaam en achternaam, we specificeren geen type, dus het is standaard een string. Voor leeftijd, we zeggen dat het een geheel getal moet zijn.

Wat doet dit eigenlijk? Je zou wat output moeten zien, dat uit te leggen. De belangrijke dingen zijn dit:

 create db / migrate / 20130213204626_create_people.rb create app / models / person.rb

Het eerste bestand is uw migratiebestand (de tijdstempel zal natuurlijk anders zijn); de tweede is jouw Ruby-klasse.

U moet vertrouwd zijn met de syntaxis van het migratiebestand, omdat u de code vaak wilt aanpassen. Laten we het bekijken.

 klasse CreatePeople < ActiveRecord::Migration def change create_table :people do |t| t.string :first_name t.string :last_name t.integer :age [ruby] t.timestamps end end end

Elke migratie is een klasse; deze heeft een enkele methode: verandering. Als u bekend bent met Ruby, zou dit vrij duidelijk moeten zijn: deze migratie maakt een tabel met de naam "mensen" in de database. Deze tabel heeft zes kolommen. Dat klopt, zes. Daar is de Voornaam, achternaam, en leeftijd velden die we hebben toegevoegd vanaf de opdrachtregel; in de create_table blokkeren gebruiken we methoden die genoemd zijn naar het gegevenstype en geven ze een symbool door met de kolomnaam.

Dan is er t.timestamps. Dit creëert nog twee kolommen in onze tabel: gemaakt bij en updated_at. Natuurlijk zijn deze van het type datum Tijd (later meer over uw type-opties). Active Record zorgt voor deze velden gedurende de levensduur van uw records, stelt ze in en past ze indien nodig aan.

De zesde en laatste kolom is ID kaart, die hier niet wordt vermeld omdat deze standaard is toegevoegd. Dat is de unieke primaire sleutel voor de tafel.

Het maken van tabellen is slechts één gebruik voor een migratieklasse; ze zijn je methode om de database aan te passen, onthoud, zodat ze elke databaseopdracht kunnen doen die je ooit zou kunnen doen. Maar een van de belangrijke ideeën met migraties is dat je ze kunt terugdraaien of hun effecten ongedaan kunt maken. Dit betekent dat elke migratieklasse voldoende informatie moet hebben om de effecten ongedaan te maken. Verschillende methoden kunnen "zichzelf ongedaan maken"; Het tegenovergestelde van het toevoegen van een tabel is bijvoorbeeld het verwijderen ervan, wat geen extra informatie vereist. Dit is de reden waarom we de verandering methode hier. Als we echter iets doen dat niet automatisch ongedaan kan worden gemaakt, moeten we de acties specificeren voor het doen en ongedaan maken van onze migratie. In deze gevallen moet onze migratieklasse twee methoden hebben: omhoog en naar beneden. De omhoog methode zal gedetailleerd beschrijven wat te doen bij het uitvoeren van de migratie, en de naar beneden methode zal uitleggen hoe de migratie teruggedraaid kan worden.

Laten we onze eigen migratie helemaal opnieuw schrijven om deze rollback-functie eens te proberen. We beginnen met het genereren van een lege migratie:

 rails g migratie do_stuff

(Normaal gesproken geeft u uw migratie een verstandige naam.)

Nu kunnen we openen db / migrate /_do_stuff.rb. Het zal de omhoog/naar beneden standaardmethoden, maar doe het en vervang dat met een single verandering methode.

 klasse DoStuff < ActiveRecord::Migration def change create_table :nothing do |t| t.string :blank end [ruby] add_column :people, :job, :string end end

We beginnen met het maken van een nutteloze tabel, met dezelfde syntaxis als de tabel hierboven. Vervolgens gebruiken we de add_column methode om een ​​kolom aan de persoonentabel toe te voegen: specifiek, a baan kolom van het type string. Beide acties kunnen eenvoudig ongedaan worden gemaakt door de tabel te verwijderen en de kolom te verwijderen.

Laten we nu onze twee migraties uitvoeren. We doen dit via een rake-taak:

 rake db: migreren

Je zou de uitvoer als volgt moeten zien:

 == CreatePeople: migrating ===================== - create_table (: people) -> 0.0027s == CreatePeople: gemigreerd (0.0034s) ==== ======== == DoStuff: migrating ========================== - create_table (: niets) -> 0.0014s - add_column (: people,: job,: string) -> 0.0008s == DoStuff: gemigreerd (0.0037s) =================

Je kunt aan de output precies zien wat er is gedaan. De eerste migratie heeft de mensen tafel; de tweede creëerde het niets tabel en de kolom toegevoegd. Laten we nu de laatste migratie ongedaan maken die we hebben uitgevoerd. We kunnen dit doen door het volgende uit te voeren:

 rake db: terugdraaien

Nogmaals, de uitvoer bevestigt:

 == DoStuff: reverting ========================== - remove_column ("people",: job) -> 0.0134s - drop_table ( "nothing") -> 0.0004s == DoStuff: teruggezet (0.0140s) =================

En nu is de migratie die we van nul hebben geschreven ongedaan gemaakt.

Een belangrijke opmerking hier: als u nog relatief onbekend bent met Rails, vergeet u misschien dat migraties niet automatisch worden uitgevoerd wanneer u een nieuw model maakt. Je moet ze handmatig uitvoeren. Ja, ik ben dit mijn redelijk aantal keren vergeten en vroeg me af wat er aan de hand was, alleen om te beseffen dat de tafel waarmee ik probeerde te werken nog niet eens bestond.

behalve create_table en add_column, er zijn een heleboel andere methoden die je in je migratiebestanden kunt gebruiken. In deze zelfstudie kunnen we niet alles bespreken, maar als ze eruit zien als iets dat u nodig heeft, bekijkt u de migratiedocumenten.

  • add_column
  • add_index
  • add_timestamps
  • change_column
  • change_table
  • create_table
  • drop_table
  • remove_column
  • remove_index
  • remove_timestamps
  • rename_column
  • rename_index
  • rename_table

Laatste opmerking over migraties: hier is een lijst met de ondersteunde typen die u in uw migratieklassen kunt gebruiken:

  • binair
  • boolean
  • datum
  • datum Tijd
  • decimale
  • vlotter
  • geheel getal
  • hoofdsleutel
  • draad
  • tekst
  • tijd
  • tijdstempel

Kijken naar de Active Record Class

Nu we de database hebben opgezet, zijn we klaar om naar het andere deel van ons model te kijken: de Active Record-klasse. Dit is het stuk waarmee je daadwerkelijk communiceert vanuit je Rails-controllers. Toen we de Persoon model, een bestand app / modellen / person.rb werd opgericht; het ziet er zo uit:

 klas Persoon < ActiveRecord::Base attr_accessible :age, :first_name, :last_name end

Als je eerder met Ruby hebt gewerkt, ben je misschien bekend met de attr_accessor methode, die de getter- en settermethoden voor de betreffende attributen maakt. Nou ja, de attr_accessible methode is anders; het is eigenlijk Rails-specifiek. Alle eigenschappen die dat zijn attr_accessible-ized kan via massatoewijzing worden ingesteld. Dit betekent alleen maar het instellen van een aantal eigenschappen tegelijk op een object; dit wordt vaak gedaan bij het maken van een object, zoals zo:

 Person.new first_name: "Andrew", achternaam: "Burgess", leeftijd: 22

Elk van de eigenschappen gedefinieerd met attr_accessible moet een van de velden zijn die we in onze databasetabellen hebben gedefinieerd, in onze migraties (er zijn een paar uitzonderingen hierop). Maar dit betekent niet dat al onze eigenschappen moeten worden gedefinieerd als toegankelijk; er kunnen een aantal eigenschappen zijn die u opzettelijk wilt instellen; bijvoorbeeld, een beheerder eigenschap die beheerdersbevoegdheden geeft voor een gebruikersrecord moet waarschijnlijk niet worden toegestaan ​​in de massatoewijzing, waar het per ongeluk / kwaadwillig kan worden ingesteld.

Voor eenvoudige Active Record-klassen, alleen die regel van attr_accessible eigenschappen zullen voldoende zijn. Er is feitelijk veel meer dat we aan onze modelklasse kunnen toevoegen om het robuuster te maken, maar laten we eerst deze person-modelrondrit nemen en zien hoe modelinstanties kunnen worden gemaakt.


Records maken

In de app "Een normale dag in het leven van een Rails" worden alle databaserecords in de controller gemaakt. In deze zelfstudie gebruiken we echter de Rails-console. In de terminal kunt u de Rails-console openen door een van de volgende handelingen uit te voeren:

 rails console rails c

Hiermee wordt een Ruby-console geopend waarin u al uw modelklassen kunt gebruiken.

Zoals je hierboven hebt gezien, kunnen we nieuwe databaserecords maken door een klasseninstantie te maken:

 p = Person.new first_name: "John", achternaam: "Doe", leeftijd: 30 # => #

De tweede regel is de waarde van onze variabele p: een nieuw Persoon voorwerp. Merk op dat drie van de zes eigenschappen zijn ingesteld, terwijl de andere drie dat niet hebben gedaan. Die worden ingesteld wanneer het record in de database wordt opgeslagen, wat het momenteel niet is (als u hebt getypt Uitgang op dit moment is er niets in de database opgeslagen). U kunt bevestigen dat het niet wordt opgeslagen door het uit te voeren

 p.new_record? # => waar

Om de record in de database op te slaan, kunt u bellen met opslaan methode:

 p.save

Let op dit deel van de output:

 INSERT IN "people" ("age", "created_at", "first_name", "last_name", "updated_at") VALUES (?,?,?,?,?) [["Age", 30], ["created_at ", Vr, 15 feb 2013 16:02:18 UTC +00: 00], [" voornaam "," John "], [" achternaam "," Doe "], [" updated_at ", vr, 15 feb 2013 16 : 02: 18 UTC +00: 00]]

Ja, dat is een SQL-statement. Let op, Active Record gebruikt de database-API eronder, dus de SQL moet nog steeds worden uitgevoerd. Dat is een van de kenmerken van de Rails-console: u kunt experimenteren met verschillende Active Record-methoden en precies zien hoe ze de database aanraken. Dit is handig als u methoden gebruikt die veel gegevens ophalen, bijvoorbeeld uit verschillende tabellen: u kunt de juiste methoden kiezen om de meest efficiënte SQL-query te krijgen.

Maar nu, bekijk ons ​​record

 p.new_record? # => valse p # => #

De ID kaart, gemaakt bij, en updated_at velden zijn ingesteld.

Als u wilt, kunt u in één keer een nieuwe record maken en opslaan met de creëren methode:

 p2 = Person.create first_name: "Jane", last_name: "Doe", leeftijd: 25 # => # p2.new_record? # => false

Wanneer u met afzonderlijke records werkt, kunt u eigenschappen instellen of wijzigen door hun individuele methoden te gebruiken; Onthoud dat het instellen van een eigenschap deze niet opslaat in de database; dat vereist de opslaan telefoontje.

 p2.first_name = "Janice" p2.save

Als u meerdere kenmerken tegelijk wilt bijwerken, kunt u de update_attributes, welke een hash neemt van al het attribuut dat je wilt wijzigen:

 p.update_attributes first_name: "Jonathan", achternaam: "Doherty"

Een belangrijk verschil over update_attributes is dat opslaan wordt binnen die methode uitgevoerd; het is niet nodig om de wijzigingen zelf op te slaan.

Zoals ik al zei, echter, er is meer dat we kunnen doen in de modelklasse. Laten we dus teruggaan naar enkele van die andere functies.


validaties

Validaties vormen een belangrijk onderdeel van elke webapp; dit is waar we ervoor zorgen dat de gegevens die we in de database plaatsen, schoon en correct zijn.

Voordat we beginnen, is het belangrijk om te beseffen dat validatieregels die in uw modelklassen zijn gemaakt, de feitelijke database niet wijzigen. Bijvoorbeeld, het zeggen van een gegeven eigenschap is vereist in uw modelklasse maakt het niet vereist op databaseniveau (dat soort dingen zou u instellen in uw - wacht erop - migraties). Dit is niet echt iets waar je je zorgen over hoeft te maken, ik wil gewoon zeker weten dat je de grote afbeelding hier begrijpt.

Zo. Validaties. In de huidige versies van Rails gebruiken we de valideert methode om al onze validaties in te stellen (het was anders in het verleden). Eerst geven we het veld door of velden die we valideren. Dan kunnen we het een hash doorgeven, de validatie-eigenschappen. Er zijn een aantal van deze validatiehulpmiddelen (zoals ze worden genoemd) die we kunnen gebruiken; hier zijn er verschillende die je altijd zult gebruiken.

Waarschijnlijk de meest gebruikelijke is alleen maar te valideren dat een bepaald veld is gevuld; hiervoor doen we een aanwezigheid validatie:

 validates: first_name,: last_name, presence: true

Hier hebben we validatie op de Voornaam en achternaam attributen. In onze validatie-eigenschappen hash, zetten we aanwezigheid naar waar, wat betekent dat die attributen niet mogen worden verlaten nul wanneer het record is opgeslagen.

Een andere veel voorkomende validatie is ervoor zorgen dat een veld uniek is. We kunnen dit doen met de unieke helper.

 valideert: gebruikersnaam, uniciteit: waar

Verschillende validatiehelpers nemen niet alleen waar of vals; ze hebben nog een paar opties nodig. Eigenlijk is de Uniciteits-helper een van hen; wanneer we het gewoon hebben ingesteld waar, zoals hierboven is hoofdlettergevoeligheid ingeschakeld. Echt waar, met gebruikersnamen, bob en BOB zou hetzelfde moeten zijn. Dus, we zouden dit moeten doen:

 validates: gebruikersnaam, uniciteit: case_sensitive: false

Nu, bob en BOB zou hetzelfde worden beschouwd.

Soms wilt u dat een eigenschap een van een reeks opties is. Proberen inclusie, die een array (of een ander opsombaar object) neemt.

 valideert: account, opname: ['gratis', 'premium', 'business']

Het tegenovergestelde van inclusie is uitsluiting, die ervoor zorgt dat de veldwaarde niet in de gegeven reeks valt:

 valideert: appt_day, exclusion: ['Sunday', 'Saturday']

Als je zeker wilt weten dat een veld een bepaalde lengte heeft? invoeren lengte. Er zijn een aantal manieren om deze te gebruiken. Hier zijn een paar voorbeelden:

 validates: gebruikersnaam, lengte: maximum: 15 validates: first_name, length: minimum: 1 validates: password, length: in: 10 ... 50

U kunt zelfs drempels instellen:

 validates: age, length: greater_than: 18 validates: commission_percentage, length: less_than: 30

Mogelijk wilt u bevestigen dat een waarde een getal is. Gebruik hiervoor numericality:

 valideert: prijs, numericiteit: waar

numericality kan ook omgaan met het beleid 'geen decimalen':

 valideert: jaar, numericiteit: only_integers: true

De laatste die ik je laat zien is formaat, waarmee u een reguliere expressie kunt instellen voor het overeenkomende veld:

 # not a real email regex validates: email, format: with: /\w_@\\\\\\\\\

Er zijn er nog een paar, maar daarmee begin je. Een laatste feitje: u kunt uw eigen valideringshelperklassen maken. Bekijk de documentatie voor meer informatie hierover.

Er zijn verschillende veelvoorkomende opties die bij bijna alle validatiehelpers passen. Ten eerste kunnen we instellen allow_nil om, nou, sta toe dat een eigenschap niet gevuld is.

 valideert: bijnaam, lengte: in: 4 ... 10, allow_nil: true

Als een lege reeks acceptabel is, kunt u de allow_blank in plaats daarvan.

Een meer gebruikelijke is bericht; als een validatie mislukt, wordt een bericht aan het object toegevoegd (hier later meer over). Uiteraard hebben alle validatiehelpers standaard berichten, maar je kunt er zelf een instellen met bericht.

 valideert: jaar, aanwezigheid: waar, bericht: "Selecteer een jaar." 

De laatste die ik noem is op, welke bepaalt op welke voorwaarden de validatie zal worden uitgevoerd. De waarden kunnen zijn : maak (de validatie wordt alleen uitgevoerd bij het opslaan van nieuwe records). :bijwerken (het wordt alleen uitgevoerd bij het opslaan van eerder opgeslagen records), of :opslaan (het wordt in beide gevallen uitgevoerd). Natuurlijk is het standaard ingesteld op :opslaan.

 validates: password, length: in: 10 ... 20, on:: create

Validatiefouten

Een model exemplaar is opslaan methode retourneert waar als het met succes is opgeslagen en vals als dat niet zo was. Als je een krijgt vals terug, wil je weten wat de fouten waren, goed?

Uw modelinstantie heeft een fout eigendom, dat is een ActiveModel :: Fouten aanleg. Nadat de validaties zijn uitgevoerd, wordt dit object gevuld met alle foutberichten voor mislukte validaties; deze worden op zichzelf gehouden berichten proptery. Let op:

 p = Persoon.new p.save # false p.errors.messages # : first_name => ["kan niet leeg zijn"],: last_name => ["kan niet leeg zijn"],: age => [ "kan niet leeg zijn", "is geen getal"] # alternatief: p.errors.full_messages # ["Voornaam mag niet leeg zijn", "Achternaam mag niet leeg zijn", "Leeftijd kan" t is blank "," Leeftijd is geen getal "]

Meestal wilt u deze fouten weergeven aan de gebruiker, waarschijnlijk naast een formulier dat ze hebben verzonden. Een van de gemakkelijkste manieren om dit te doen is om over de full_messages eigendom van binnenuit uw form_for blokkeren en ze in een lijst of iets dergelijks afdrukken. Nog eenvoudiger is om Rails al die markup door te laten werken form.error_messages.


callbacks

Terugbellen is een ander cool onderdeel van Active Record; ze laten je op een bepaald moment aangepaste methoden uitvoeren. Als je mijn Building Ribbit in Rails handleiding leest, weet je misschien nog dat we de before_save terugbellen om de avatar_hash eigendom van gebruikers voordat ze worden opgeslagen. We maken eerst de methode die we willen uitvoeren:

 def create_avatar_hash self.avatar_hash = "http://www.gravatar.com/avatar/#Digest::MD5.hexdigest(self.email)?s=50" end

En dan registreren we gewoon de callback:

 before_save: create_avatar_hash

Dit betekent dat wanneer we bellen opslaan, onze methode wordt uitgevoerd net voordat het opslaan daadwerkelijk is voltooid.

We gebruikten ook een before_validation terugbellen om het e-mailadres te verwijderen. Hoewel dit slechts twee van de callbacks zijn die u kunt gebruiken, zijn dit goede voorbeelden van deze callbacks die handig kunnen zijn. Dit zijn de anderen:

  • before_validation / after_validation
  • before_save / around_save / after_save
  • before_create / around_create / after_create
  • before_update / around_update / after_update
  • before_destroy / around_destroy / after_destroy

Vraagt ​​u zich af over de in de omgeving van_* callbacks? Dit zijn best cool. Ze worden opgeroepen voordat de actie is voltooid, maar dan kun je de actie vanuit de methode uitvoeren door te callen opbrengst. Zodra de actie is voltooid, wordt de reset van de callback-methode uitgevoerd. Gaaf he?


verenigingen

De meeste relationele databases hebben meerdere tabellen die op de een of andere manier met elkaar in verband staan. Het is dus logisch dat Active Record dit kan verwerken: het doet dit via actieve recordkoppelingen. Laten we zeggen dat we een willen hebben Bestellen tabel in onze database, en dat elk Persoon kan meerdere bestellingen hebben. Hoe krijg je dit ingesteld?

We moeten beginnen met het maken van onze Bestellen model:

 rails g model Ordertotaal: integer person_id: integer

Het belangrijkste onderdeel hier is de person_id veld; zoals je zou verwachten, zal dit onze buitenlandse sleutel zijn, de verbinding tussen de twee klassen. We noemen het person_id omdat, zodra we onze modelklassen over de relatie vertellen, de Bestellen klasse zoekt standaard naar een veld met die naam. Als we het iets anders wilden noemen, zoals orderer_identifier, we zouden het moeten vertellen Bestellen dat het veld niet is vernoemd naar de klas waarmee het verbinding maakt. Het is gemakkelijker om met de standaardinstellingen te werken.

De migratie die met deze opdracht wordt gemaakt, is alles wat we nodig hebben, dus ik ga nu migreren:

 rake db: migreren

Nu moeten we de klassen informeren over de relatie. Binnen in de app / model / person.rb, voeg deze regel toe:

 has_many: bestellingen

Nu in app / model / order.rb, Voeg dit toe:

 behoort_naar: persoon

In Persoon, we zeggen dat er veel orders kunnen zijn voor elk persoonsbestand; anders gezegd, elke persoon heeft veel orders. Omgekeerd, elke bestelling hoort bij een persoon instantie. Deze voegen gewoon een paar handige methodes toe aan onze Persoon en Bestellen instanties, die we in een beetje zullen zien.

Dus laten we deze relatie testen, zullen we? In de Rails-console:

 p = Person.find (1) o = Order.new total: 100 o.person = p o.save p.orders # => [#]

De interessante regels hier zijn 3 en 5. We hadden het kunnen doen o.person_id = p.id, maar vanwege onze toevoegingen aan de modellessen, o.person = p is een kortere manier om hetzelfde te doen. Dan regel 5: dit is weer een van die toegevoegde methoden: het geeft een reeks van alle orders terug die onze persoon heeft. Handig, nee?

Dit is een goede samenvatting van het soort dingen dat u kunt doen met Active Record Associations; er is een ton meer, en het kan behoorlijk ingewikkeld worden. Bekijk de documentatie van de Verenigingen voor al het goede.


Records selecteren

Al die tijd hebben we Active Record-klassen gebouwd of modelrecords gemaakt. Een groot deel van het werken met een Active Record-klasse is echter om die records terug te krijgen. Zoals je zou verwachten, zijn er een tiental methoden die we kunnen gebruiken.

De eerste en eenvoudigste zijn de methoden die alle records retourneren:

 Person.all

De allemaal methode retourneert een array van alle records.

Er is ook vind, welke de ID kaart als een parameter en retourneert de record met die id; het kan ook een reeks van aannemen ID kaarts en retourneer de overeenkomende records:

 Person.find 2 # => # Person.find [2,4,6] # => [#, #, # ]

Als u alleen de eerste of laatste record in de verzameling wilt, zijn daarvoor specifieke methoden:

 Person.eerst Person.last

Een van de coolste functies van Active Record is de aangepaste vindmethode; daaronder, dit gebruikt het gewoon method_missing, maar vanaf de bovenkant lijkt het pure magie. Hier is hoe het werkt: gebruik de methode naam find_by_ en geef de waarde voor die eigenschap door als parameter. Bijvoorbeeld:

 Person.find_by_first_name "John" # => #

Je kunt zelfs eigenschappen koppelen; deze opdracht retourneert hetzelfde record:

 Person.find_by_first_name_and_last_name "John", "Doe"

Als u de SQL-query's voor die laatste twee methoden bekijkt, ziet u dat we alleen het eerste resultaat retourneren (LIMIET 1). Om alle gevonden records te vinden, gebruikt u de find_all_by voorvoegsel. Zo:

 Person.find_all_by_first_name "John" Person.find_all_by_first_name_and_last_name "John", "Doe"

Het wordt nog beter: je kunt het gebruiken find_or_create_by voorvoegsel om een ​​record aan te maken als er geen overeenkomende gevonden wordt:

 p = Person.find_or_create_by_first_name_and_last_name_and_age "Bob", "Smith", 45

Ja, dit werkt echt. Realiseer je echter dat als er geen record wordt gevonden, dit hetzelfde is als hardlopen Person.create, welke de validaties uitvoert. Dus, bijvoorbeeld, sinds achternaam en leeftijd vereist zijn, als dit wordt uitgevoerd, zullen er niet-opgeslagen fouten in de record worden aangebracht:

 Person.find_or_create_by_first_name "Lindsey"

Als u niet wilt dat de nieuwe record meteen wordt opgeslagen, gebruikt u de find_or_initialize_by voorvoegsel.

 Person.find_or_initialize_by_first_name "Lindsey"

Er zijn een paar andere methoden die u mogelijk handig vindt bij het selecteren van records. Een heel nuttige is waar wat een WAAR clausule uit een SQL-instructie.

 Person.where ("first_name like 'A%'")

Als u waarden van de gebruiker gebruikt voor gebruik in waar, je moet ze niet interpoleren, uit angst voor SQL-injecties. U moet vraagtekens gebruiken in plaats daarvan en de waarden vervolgens als andere parameters doorgeven:

 Person.where ("first_name like?", Params [: name_starts_with])

... of iets dergelijks.

Al deze methoden die we tot nu toe hebben bekeken, retourneren alle velden van de geretourneerde records. U kunt de kiezen methode vóór een van hen om modelinstances alleen met een paar geselecteerde eigenschappen te retourneren:

 Person.select (: first_name) .First Person.select ("last_name, age"). Find_by_first_name ("Andrew")

Andere veel voorkomende activiteiten voor SQL-instructies omvatten beperken en compenseren; een goed voorbeeld hiervan is pagineringsresultaten. De begrenzing en compenseren methoden nemen elk een enkele getalparameter. Als je ze alleen gebruikt, werken ze aan de hele verzameling; dit levert bijvoorbeeld vijf records op en slaat de eerste twee over:

 Person.offset (2) .limit (5)

Maar u kunt de records kiezen om te beperken en te compenseren met een van de andere functies:

 Person.select (: id) .limit (2) .offset (2) .find_all_by_first_name "Andrew"

Er zijn een paar andere query-methoden, maar we hebben degenen behandeld die u 90% van de tijd gaat gebruiken.

Als u complexe query's als deze uitvoert, is het een goed idee om zelf een querymethode te maken, in uw modellessen. Laten we zeggen dat we mensen laten zoeken naar andere gebruikers op hun achternaam, en we publiceren de resultaten met 10 gebruikers per pagina. De zoekopdracht kan er ongeveer zo uit zien:

 Person.offset (0) .limit (10) .find_by_last_name (params [: SEARCH_TERM])

Behalve dat dit nogal lang is voor de controller, moet die offset voor elke pagina veranderen; 0 werkt alleen voor de eerste pagina. Dus, we schrijven een methode in onze Persoon klasse:

 def self.search (term, pagina = 1, per_page = 10) Persoon.offset (per_page * (pagina - 1)). limit (per_page) .find_all_by_last_name term einde

Dit geeft de set terug die we willen, en we kunnen kiezen welke pagina en hoeveel resultaten per pagina we willen hebben (of laten ze naar hun verstandige standaardwaarden.) En nog beter, het is een mooie nette methode die we kunnen bellen vanuit onze controller zoals deze. :

 Person.search "Smith" # pagina 1 Person.search "Smith", 2 # pagina 2

Raadpleeg voor meer informatie over query's de query-documentatie voor Active Record.


Conclusie

Als u Rails net wilt gebruiken, heeft u zojuist alles geleerd over Active Record voor een tijdje. Natuurlijk, zoals elk ander onderdeel van Rails, is Active Record diep en rijk;