Record attivo il ponte del database di Rails

In passato, per creare un'applicazione Web, è necessario acquisire le competenze necessarie per codificare la lingua della logica aziendale e la lingua del database. Più recentemente, tuttavia, i framework di back-end si stanno orientando verso l'utilizzo di Object-Relational Mapping (ORM); questa è una tecnica che ti consente di gestire il tuo database nel linguaggio della business logic con cui ti trovi più a tuo agio.

Rails utilizza un ORM sotto forma di Active Record. In questo tutorial, ci tufferemo in Active Record e vediamo cosa può fare per noi!


Che cos'è il record attivo, esattamente

Come ho detto, Active Record è un ORM. Ciò significa che si tratta di un livello di codice Ruby che viene eseguito tra il tuo database e il tuo codice logico. Quando devi apportare modifiche al database, scrivi il codice Ruby e quindi esegui le migrazioni, che esamineremo a breve. Queste migrazioni apportano le modifiche effettive al database. La parte interessante è che non importa quale database stai usando: Rails può gestirli praticamente tutti. Ad esempio, Rails utilizza SQLite localmente durante lo sviluppo. Tuttavia, diciamo che stai distribuendo su Heroku, che usa PostreSQL. Tutto quello che devi fare è aggiungere questo al tuo Gemfile:

 gruppo: produzione fai gemma 'pg' fine

Ora, quando si distribuisce, Heroku eseguirà le stesse migrazioni (usando l'adattatore PostgreSQL). Stesso codice, database differente, che è abbastanza bello, secondo me.

Quindi, questo è ciò che Active Record è; scaviamo più a fondo e vediamo come funziona.


Iniziare

Mentre è tecnicamente possibile utilizzare Active Record all'esterno dell'app Rails, nove volte su dieci lo utilizzerai entro un'app Rails, ecco cosa faremo qui. Sto usando Rails 3.2.12, l'ultima versione mentre scrivo questo. Se hai installato quello, puoi iniziare creando una nuova app Rails.

 rota nuova myapp cd myapp

Ora possiamo iniziare creando un modello.


Creazione di modelli e migrazioni

Come ci si potrebbe aspettare, dal momento che Active Record interagisce con il database, è il M nel MVC di Rails: Modelli. Dalla riga di comando, creeremo un modello per, diciamo, una persona. In realtà, il rotaie generano il comando è abbastanza flessibile: tutti i seguenti comandi funzionano:

 rotaie generano modello Persona rotaie g modello Persona rotaie g modello Persona first_name last_name age: intero

Le prime due righe qui fanno la stessa cosa; binari g è solo una scorciatoia per rotaie generano. Il terzo dà a Rails qualche informazione in più, quindi può fare un po 'più di lavoro per noi. Stiamo dicendo che vogliamo che questo modello abbia tre campi: nome di battesimo, cognome, e età. Per nome di battesimo e cognome, non specifichiamo un tipo, quindi ha come valore predefinito una stringa. Per età, diciamo che dovrebbe essere un numero intero.

Quindi, cosa fa in realtà? Dovresti vedere qualche risultato, spiegandolo. I bit importanti sono questi:

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

Il primo file è il tuo file di migrazione (ovviamente, il timestamp sarà diverso); la seconda è la tua classe Ruby.

Dovresti essere a tuo agio con la sintassi del file di migrazione, perché spesso desideri regolare il codice. Controlliamolo.

 classe 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

Ogni migrazione è una classe; questo ha un solo metodo: modificare. Se hai familiarità con Ruby, questo dovrebbe essere abbastanza auto esplicativo: questa migrazione crea una tabella denominata "persone" nel database. Questa tabella ha sei colonne. Esatto, sei. C'è il nome di battesimo, cognome, e età campi che abbiamo aggiunto dalla riga di comando; nel crea tabella blocco, usiamo i metodi che prendono il nome dal tipo di dati e passiamo loro un simbolo con il nome della colonna.

Quindi, c'è t.timestamps. Questo crea altre due colonne nella nostra tabella: created_at e updated_at. Naturalmente, questi sono di tipo appuntamento (più sulle opzioni del tuo tipo più tardi). Active Record si prende cura di questi campi per tutta la durata dei record, impostandoli e aggiornandoli quando appropriato.

La sesta e ultima colonna è id, che non è elencato qui perché è aggiunto per impostazione predefinita. Questa è la chiave primaria unica per il tavolo.

La creazione di tabelle è solo un uso per una classe di migrazione; sono il tuo metodo di modifica del database, ricorda, in modo che possano fare qualsiasi lavoro di database che potrebbe mai essere necessario fare. Ma una delle idee più importanti con le migrazioni è che puoi eseguire il rollback o annullare i loro effetti. Ciò significa che ogni classe di migrazione deve disporre di informazioni sufficienti per annullare i suoi effetti. Diversi metodi possono "annullare se stessi"; ad esempio, l'opposto dell'aggiunta di una tabella lo sta rimuovendo, il che non richiede alcuna informazione aggiuntiva. Questo è il motivo per cui possiamo usare il modificare metodo qui. Tuttavia, se stessimo facendo qualcosa che non può essere automaticamente annullato, dobbiamo specificare le azioni per fare e annullare la nostra migrazione. In questi casi, la nostra classe di migrazione dovrebbe avere due metodi: su e giù. Il su il metodo spiegherà cosa fare durante l'esecuzione della migrazione e giù il metodo spiegherà come eseguire il rollback della migrazione.

Scriviamo la nostra migrazione da zero per provare questa funzionalità di rollback. Iniziamo generando una migrazione vuota:

 rails g migration do_stuff

(Normalmente, darai alla tua migrazione un nome sensato).

Ora possiamo aprire db / migrate /_do_stuff.rb. Avrà il su/giù metodi per impostazione predefinita, ma fare avanti e sostituirlo con un singolo modificare metodo.

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

Iniziamo creando un tavolo inutile, con una sintassi simile alla nostra tabella persone sopra. Quindi, usiamo il add_column metodo per aggiungere una colonna alla tabella delle persone: in particolare, a lavoro colonna di tipo stringa. Entrambe queste azioni possono essere facilmente annullate, lasciando cadere la tabella e rimuovendo la colonna.

Ora, eseguiamo le nostre due migrazioni. Lo facciamo tramite un compito di rake:

 rake db: migrate

Dovresti vedere un output come questo:

 == CreatePeople: migrazione ===================== - create_table (: people) -> 0.0027s == CreatePeople: migrated (0.0034s) ==== ========== DoStuff: migrazione ========================== - create_table (: nothing) -> 0.0014 s - add_column (: people,: job,: string) -> 0.0008s == DoStuff: migrato (0.0037 s) =================

Puoi vedere dall'output esattamente ciò che è stato fatto. La prima migrazione ha creato il persone tavolo; il secondo ha creato il Niente tabella e ha aggiunto la colonna. Ora, annulliamo l'ultima migrazione che abbiamo eseguito. Possiamo farlo eseguendo quanto segue:

 rake db: rollback

Di nuovo, l'output conferma:

 == DoStuff: ripristino ========================== - remove_column ("persone",: lavoro) -> 0.0134s - drop_table ( "niente") -> 0.0004s == DoStuff: ripristinato (0.0140s) =================

E ora, la migrazione che abbiamo scritto da zero è stata annullata.

Una nota importante qui: se sei relativamente nuovo a Rails, potresti dimenticare che le migrazioni non vengono eseguite automaticamente quando crei un nuovo modello. Devi eseguirli manualmente. Sì, ho dimenticato questa mia buona dose di volte, e mi sono chiesto cosa stesse succedendo, solo per rendermi conto che il tavolo con cui stavo cercando di lavorare non esisteva ancora.

inoltre crea tabella e add_column, ci sono molti altri metodi che puoi usare nei tuoi file di migrazione. Non possiamo esaminarli tutti in questo tutorial, ma se sembrano qualcosa di cui hai bisogno, dai un'occhiata ai documenti di migrazione.

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

Ultima nota sulle migrazioni: ecco un elenco dei tipi supportati che è possibile utilizzare nelle classi di migrazione:

  • binario
  • booleano
  • Data
  • appuntamento
  • decimale
  • galleggiante
  • numero intero
  • chiave primaria
  • stringa
  • testo
  • tempo
  • timestamp

Guardando la classe Active Record

Ora che abbiamo impostato il database, siamo pronti a guardare l'altra parte del nostro modello: la classe Active Record. Questo è il pezzo con cui interagirai realmente dai tuoi controller Rails. Quando abbiamo creato il Persona modello, un file app / modelli / person.rb è stata creata; sembra così:

 classe Persona < ActiveRecord::Base attr_accessible :age, :first_name, :last_name end

Se hai già lavorato con Ruby, potresti avere familiarità con attr_accessor metodo, che rende i metodi getter e setter per gli attributi in questione. Bene, il attr_accessible il metodo è diverso; in realtà è specifico di Rails. Qualsiasi proprietà che sia attr_accessible-ized può essere impostato tramite l'assegnazione di massa. Questo significa semplicemente impostare un gruppo di proprietà su un oggetto contemporaneamente; questo è spesso fatto quando si crea un oggetto, in questo modo:

 Person.new first_name: "Andrew", last_name: "Burgess", età: 22 anni

Ciascuna delle proprietà definite con attr_accessible deve essere uno dei campi che abbiamo definito nelle nostre tabelle di database, nelle nostre migrazioni (ci sono alcune eccezioni a questo). Ma questo non significa che tutte le nostre proprietà dovrebbero essere definite come accessibili; potrebbero esserci alcune proprietà che si desidera impostare in modo più intenzionale; per esempio, a Admin la proprietà che conferisce privilegi di amministrazione a un record utente probabilmente non dovrebbe essere consentita in assegnazione di massa, dove potrebbe essere impostata accidentalmente / maliziosamente.

Per semplici classi di record attivi, solo quella linea di attr_accessible le proprietà saranno sufficienti. In realtà possiamo aggiungere molto di più alla nostra classe del modello per renderla più solida, ma prima prendiamo questo round-trip del modello Person e vediamo come creare le istanze del modello.


Creazione di record

In "Una giornata normale nell'app di Life of a Rails", tutti i record del database verranno creati nel controller. Tuttavia, utilizzeremo la console Rails in questo tutorial. Nel terminale, è possibile aprire la console di Rails eseguendo una delle seguenti operazioni:

 rotaie per consolle rotaie c

Si apre una console Ruby in cui è possibile utilizzare tutte le classi del modello.

Come hai visto sopra, possiamo creare nuovi record di database creando un'istanza di classe:

 p = Person.new first_name: "John", last_name: "Doe", età: 30 # => #

La seconda riga è il valore della nostra variabile p: una nuova Persona oggetto. Si noti che tre delle sei proprietà sono state impostate, mentre le altre tre non lo sono state. Quelli saranno impostati quando il record viene salvato nel database, che attualmente non è (se hai digitato Uscita in questo momento, nulla sarà stato memorizzato nel database). Puoi confermare che non è stato salvato eseguendo

 p.new_record? # => true

Per salvare il record nel database, è possibile chiamare il salvare metodo:

 p.save

Si noti questa parte dell'output:

 INSERISCI IN "people" ("age", "created_at", "first_name", "last_name", "updated_at") VALORI (?,?,?,?,?) [["Età", 30], ["created_at ", Ven, 15 feb 2013 16:02:18 UTC +00: 00], [" first_name "," John "], [" last_name "," Doe "], [" updated_at ", ven, 15 feb 2013 16 : 02: 18 UTC +00: 00]]

Sì, questa è una dichiarazione SQL. Ricorda che Active Record sta utilizzando l'API del database sottostante, quindi l'SQL deve ancora essere eseguito. Questa è una delle funzionalità della console di Rails: puoi sperimentare diversi metodi di Active Record e vedere esattamente come stanno toccando il database. Ciò sarà utile quando stai eseguendo metodi che estraggono molti dati, magari da più tabelle: puoi scegliere i metodi giusti per ottenere la query SQL più efficiente.

Ma ora, dai un'occhiata al nostro disco

 p.new_record? # => false p # => #

Il id, created_at, e updated_at i campi sono stati impostati.

Se lo desideri, puoi creare e salvare un nuovo record tutto in una volta, con creare metodo:

 p2 = Person.create first_name: "Jane", last_name: "Doe", età: 25 # => # p2.new_record? # => falso

Quando si lavora con singoli record, è possibile impostare o modificare qualsiasi proprietà utilizzando i propri metodi individuali; ricorda che l'impostazione di una proprietà non la salva nel database; ciò richiede il salvare chiamata.

 p2.first_name = "Janice" p2.save

Se si desidera aggiornare più attributi alla volta, è possibile utilizzare il update_attributes, che prende un hash di tutto l'attributo che vuoi cambiare:

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

Una differenza importante in merito update_attributes è questo salvare è eseguito all'interno di quel metodo; non è necessario salvare le modifiche da solo.

Come ho detto, però, c'è di più che possiamo fare nella classe del modello. Quindi torniamo indietro e guardiamo alcune di queste altre funzionalità.


Validazioni

Le convalide sono una parte importante di qualsiasi app web; è qui che ci assicuriamo che i dati che stiamo inserendo nel database siano puliti e corretti.

Prima di iniziare, è importante rendersi conto che le regole di convalida create nelle classi del modello non modificano il database effettivamente. Ad esempio, affermare che una determinata proprietà è richiesta nella classe del modello non la rende necessaria a livello di database (quel tipo di cose che si imposterebbero nelle migrazioni-wait-it-it). Questo non è qualcosa di cui ti devi preoccupare, voglio solo assicurarmi di capire il quadro generale qui.

Così. Convalide. Nelle versioni correnti di Rails, usiamo il Convalida metodo per impostare tutte le nostre convalide (era altrimenti nel passato). Per prima cosa, passiamo il campo oi campi che stiamo convalidando. Quindi, possiamo passargli un hash le proprietà di validazione. Ci sono un sacco di questi helper di validazione (come vengono chiamati) che possiamo usare; eccone diversi che userete sempre.

Probabilmente il più comune è solo la convalida del completamento di un dato campo; per questo, facciamo a presenza convalida:

 convalida: first_name,: last_name, presence: true

Qui, abbiamo convalidato su nome di battesimo e cognome attributi. Nel nostro hash delle proprietà di convalida, abbiamo impostato presenza a vero, il che significa che quegli attributi non devono essere lasciati zero quando il record è salvato.

Un'altra convalida comune è assicurarsi che un campo sia unico. Possiamo farlo con l'aiuto dell'unicità.

 convalida: username, unicità: true

Diversi aiutanti di validazione non prendono solo vero o falso; hanno bisogno di qualche altra opzione. In realtà, l'helper dell'unicità è uno di questi; quando l'abbiamo appena impostato vero, come sopra, la distinzione maiuscole / minuscole è attiva. Davvero, però, con nomi utente, peso e BOB dovrebbe essere lo stesso Quindi, dovremmo fare questo:

 convalida: nome utente, unicità: case_sensitive: false

Adesso, peso e BOB sarebbe considerato lo stesso.

A volte vorrai che una proprietà sia una di una serie di opzioni. Provare inclusione, che accetta un array (o qualsiasi altro oggetto enumerabile).

 convalida: account, inclusione: ['free', 'premium', 'business']

Il contrario di inclusione è esclusione, che si assicura che il valore del campo non sia nel set dato:

 valida: appt_day, esclusione: ['Sunday', 'Saturday']

Se vuoi assicurarti che un campo abbia una determinata lunghezza? accedere lunghezza. Ci sono molti modi per usare questo. Qui ci sono un paio di esempi:

 valida: username, lunghezza: maximum: 15 validate: first_name, length: minimum: 1 validates: password, length: in: 10 ... 50

Puoi persino impostare le soglie:

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

Potresti voler confermare che un valore è un numero. Per questo, usa numericality:

 convalida: prezzo, numericalità: vero

numericality può anche gestire una politica "senza decimali":

 convalida: anno, numericalità: only_integers: true

L'ultimo che ti mostrerò è formato, che ti consente di impostare un'espressione regolare affinché il campo corrisponda:

 # non una vera e propria regex dell'e-mail valida: email, formato: con: /\w_@\w_.\w*/

Ce ne sono altri, ma questo ti farà iniziare. Un ultimo bocconcino: puoi creare le tue classi di helper di validazione. Controlla la documentazione per i dettagli su questo.

Esistono diverse opzioni comuni che riguardano quasi tutti gli helper di convalida. In primo luogo, possiamo impostare allow_nil per, bene, consentire che una proprietà non venga riempita.

 valida: nickname, length: in: 4 ... 10, allow_nil: true

Se una stringa vuota è accettabile, è possibile utilizzare il allow_blank anziché.

Uno più comune è Messaggio; se una convalida fallisce, un messaggio sarà allegato all'oggetto (più su questo più tardi). Ovviamente, tutti gli helper di convalida hanno messaggi predefiniti, ma è possibile impostarne uno proprio Messaggio.

 convalida: anno, presenza: true, messaggio: "Selezionare un anno". 

L'ultimo che menzionerò è sopra, che decide su quali condizioni verrà eseguita la validazione. I valori possono essere :creare (la convalida viene eseguita solo quando si salvano nuovi record). :aggiornare (viene eseguito solo quando si salvano i record salvati in precedenza) o :salvare (è eseguito in entrambi i casi). Certo, il valore predefinito è :salvare.

 convalida: password, lunghezza: in: 10 ... 20, su:: crea

Errori di convalida

Un'istanza di modello salvare metodo restituisce vero se è stato salvato con successo e falso se non lo fosse. Se ottieni un falso indietro, vorrai sapere quali erano gli errori, giusto?

L'istanza del modello ha un errore proprietà, che è un ActiveModel :: Errori esempio. Dopo l'esecuzione delle convalide, questo oggetto viene popolato con tutto il messaggio di errore per le convalide fallite; questi sono tenuti in proprio messaggi proptery. Osservare:

 p = Person.new p.save # false p.errors.messages # : first_name => ["non può essere vuoto"],: last_name => ["non può essere vuoto"],: age => [ "non può essere vuoto", "non è un numero"] # in alternativa: p.errors.full_messages # ["Il nome non può essere vuoto", "Il cognome non può essere vuoto", "L'età può" t essere bianco "," L'età non è un numero "]

Di solito, ti consigliamo di visualizzare questi errori all'utente, probabilmente accanto a un modulo che hanno inviato. Uno dei modi più semplici per farlo è quello di scorrere su full_messages proprietà dall'interno del tuo form_for bloccare e stamparli in un elenco o qualcosa del genere. Ancora più semplice è lasciare che Rails gestisca tutto quel markup eseguendo form.error_messages.


callback

Le callback sono un'altra parte interessante di Active Record; ti consentono di eseguire metodi personalizzati a determinati orari. Se leggi il mio tutorial su Building Ribbit in Rails, potresti ricordare che abbiamo usato il before_save callback per impostare il avatar_hash proprietà sugli utenti prima di salvarli. Per prima cosa creiamo il metodo che vogliamo eseguire:

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

E quindi registriamo il callback:

 before_save: create_avatar_hash

Questo significa che quando chiamiamo salvare, il nostro metodo verrà eseguito appena prima che il salvataggio venga effettivamente eseguito.

Abbiamo anche usato un before_validation richiamata per rimuovere e scollegare l'indirizzo email. Sebbene questi siano solo due dei callback che puoi usare, sono buoni esempi di questi callback che possono essere utili. Ecco gli altri:

  • 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

Chiedendo il in giro_* callback? Questi sono piuttosto interessanti. Vengono chiamati prima che l'azione venga eseguita, ma in tal caso è possibile eseguire l'azione all'interno del metodo chiamando dare la precedenza. Una volta eseguita l'azione, viene eseguito il ripristino del metodo di callback. Fantastico, eh?


associazioni

La maggior parte dei database relazionali avrà più tabelle correlate in qualche modo, quindi è naturale che Active Record sia in grado di gestirlo: lo fa attraverso Active Record Associations. Diciamo che vogliamo avere un Ordine tabella nel nostro database, e che ciascuno Persona può avere più ordini. Come ottenere questo set up?

Dobbiamo iniziare creando il nostro Ordine modello:

 rails g model Totale ordini: intero person_id: intero

La parte importante qui è la person_id campo; come ci si potrebbe aspettare, questa sarà la nostra chiave straniera, la connessione tra le due classi. Lo chiamiamo person_id perché, una volta che comunichiamo le nostre classi modello sulla relazione, il Ordine la classe cercherà un campo con quel nome per impostazione predefinita. Se volessimo chiamarlo qualcos'altro, come orderer_identifier, dovremmo dirlo Ordine che il campo non ha il nome della classe a cui si sta connettendo. È più facile andare con le impostazioni predefinite.

La migrazione creata da questo comando sarà tutto ciò di cui abbiamo bisogno, quindi eseguirò la migrazione ora:

 rake db: migrate

Ora, dobbiamo informare le classi sulla relazione. Dentro il app / modello / person.rb, aggiungi questa linea:

 has_many: ordini

Ora in app / modello / order.rb, Aggiungi questo:

 appartiene a: persona

Nel Persona, stiamo dicendo che ci possono essere molti ordini per ogni record personale; mettere diversamente, ogni persona ha molti ordini. Viceversa, ogni ordine appartiene a una istanza di persona. Questi aggiungono solo alcuni metodi utili al nostro Persona e Ordine istanze, che vedremo tra un po '.

Quindi, testiamo questa relazione, vero? Nella console di Rails:

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

Le linee interessanti qui sono 3 e 5. Avremmo potuto fare o.person_id = p.id, ma a causa delle nostre aggiunte alle classi modello, o.person = p è un modo più breve di fare la stessa cosa Quindi, riga 5: questo è un altro di questi metodi aggiunti: restituisce una matrice di tutti gli ordini che la nostra persona ha. Pratico, no?

Questo è un buon riassunto del tipo di cose che puoi fare con Active Record Associations; ce n'è ancora un sacco e può diventare piuttosto complesso. Controlla la documentazione dell'Associazione per tutta la bontà.


Selezione dei record

Per tutto questo tempo abbiamo creato classi Active Record o creato record di modelli. Tuttavia, gran parte del lavoro con una classe Active Record sta riportando quei record indietro. Come ci si potrebbe aspettare, ci sono una dozzina di metodi che possiamo usare.

Il primo, e il più semplice, sono i metodi che restituiscono tutti i record:

 Person.all

Il tutti metodo restituisce un array di tutti i record.

C'è anche trova, che prende il id come parametro e restituisce il record con quell'ID; può anche prendere una serie di ids e restituisce i record corrispondenti:

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

Se vuoi solo il primo o l'ultimo record della collezione, ci sono metodi specifici per questo:

 Person.first Person.last

Una delle funzionalità più interessanti di Active Record è i metodi di ricerca personalizzati; sotto, questo è solo usando method_missing, ma dall'alto sembra pura magia. Ecco come funziona: usa il nome del metodo find_by_ e passare il valore per quella proprietà come parametro. Per esempio:

 Person.find_by_first_name "John" # => #

Puoi persino concatenare le proprietà; questo comando restituirà lo stesso record:

 Person.find_by_first_name_and_last_name "John", "Doe"

Se osservi le query SQL per gli ultimi due metodi, vedrai che restituiremo solo il primo risultato (LIMITE 1). Per trovare tutti i record che corrispondono, utilizzare il find_all_by prefisso invece. Così:

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

Diventa ancora migliore: puoi usare il find_or_create_by prefisso per creare un record se non ne trova uno corrispondente:

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

Sì, funziona davvero. Tuttavia, renditi conto che se non viene trovato alcun record, questo è proprio come correre Person.create, che esegue le convalide. Quindi, per esempio, da allora cognome e età sono obbligatori, l'esecuzione di questo comando comporterà la presenza di errori in un record non salvato:

 Person.find_or_create_by_first_name "Lindsey"

Se non vuoi che il nuovo record venga salvato immediatamente, usa il find_or_initialize_by prefisso.

 Person.find_or_initialize_by_first_name "Lindsey"

Ci sono alcuni altri metodi che potresti trovare utili quando selezioni i record. Uno veramente utile dove che prende un DOVE clausola da una dichiarazione SQL.

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

Se stai prendendo valori dall'utente per l'uso in dove, non dovresti interpolarli, per paura delle iniezioni SQL. Dovresti utilizzare i punti interrogativi al loro posto e quindi passare i valori come altri parametri:

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

... o qualcosa di simile.

Tutti questi metodi che abbiamo esaminato finora restituiscono tutti i campi dei record restituiti. Puoi usare il selezionare metodo prima di qualsiasi di esse per restituire solo le istanze del modello con alcune proprietà selezionate:

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

Altre comuni attività delle istruzioni SQL includono la limitazione e la compensazione; un ottimo caso d'uso per questi è il paging. Il limite e compensare i metodi accettano un singolo parametro numerico ciascuno. Se li usi da soli, lavorano sull'intera collezione; per esempio, questo restituisce cinque record, saltando i primi due:

 Person.offset (2) .limit (5)

Ma puoi scegliere i record da limitare e compensare con una delle altre funzioni:

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

Esistono alcuni altri metodi di query, ma abbiamo coperto quelli che utilizzerai il 90% delle volte.

Se stai facendo query complesse come questa, sarebbe una buona idea creare un tuo metodo di query, nelle tue classi modello. Diciamo che permettiamo alle persone di cercare altri utenti con il loro cognome e paghiamo i risultati con 10 utenti per pagina. La query potrebbe essere simile a questa:

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

Oltre a essere piuttosto lungo per il controller, quell'offset deve cambiare per ogni pagina; 0 funziona solo per la prima pagina. Quindi, scriviamo un metodo nel nostro Persona classe:

 def self.search (term, page = 1, per_page = 10) Person.offset (per_page * (page - 1)). limit (per_page) .find_all_by_last_name term end

Ciò restituisce il set che vogliamo, e possiamo scegliere la pagina e il numero di risultati per pagina desiderati (o lasciarli alle loro impostazioni predefinite e, ancora meglio, è un bel metodo pulito che possiamo chiamare dal nostro controller come questo :

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

Per ulteriori informazioni sulla query, controllare la documentazione di query di Active Record.


Conclusione

Se ti stai avvicinando a Rails, hai appena imparato quasi tutto ciò che devi sapere su Active Record per un po '. Ovviamente, come ogni altra parte di Rails, Active Record è profondo e ricco; ci sono molti pezzi che non ho menzionato in questo tutorial. Per saperne di più su quelli, guarda le