2014-11-20 23 views
25

Supponiamo di avere un modello User con attributi :id, :first_name, :last_name, and :email. Nella mia applicazione, gli utenti ospiti non dovrebbero vedere User's email and last_name. Io so come selezionare valori specifici se voglio un elenco di utenti, ma non so come posso ottenere gli attributi specifici di un utente specifico comeOttieni attributi specifici da un modello ActiveRecord

User.find_by(id: 5).select(:id, :first_name). 

Una soluzione a questo è per l'utente

User.find_by(id: 5).attributes.slice('id', 'first_name') 

ma poi ottengo un hash invece di un record AR. Potrei fare

User.select(:id, :first_name).find_by(id: 1) 

ma la cosa che non so quali filtri dovrei filtrare poiché ho bisogno di conoscere prima l'utente.

Potrebbe aiutarmi?

+0

Come si fa a distinguere un utente ** ** ospite da un utente normale ** **? – Pavan

risposta

62

Cosa Choco detto funziona se si desidera un array non un'istanza record attivo. Se si desidera un'istanza record attiva, fare:

User.where(id: 5).select(:id, :first_name).take 

Ecco alcune ulteriori informazioni. Non sono sicuro di quanto tu sappia/non so, quindi presumo che tu sappia di meno piuttosto che di più.

Immagino che tu ti renda conto che quello che stai facendo sopra è il concatenamento del metodo, cioè, stai chiamando un metodo, quindi chiama un altro metodo sul risultato del primo metodo. Per esempio:

User.find_by(id: 5).attributes.slice('id', 'first_name') 

Stai chiamando il metodo find_by_id sulla classe User. Questo metodo restituirà un'istanza della classe User (ovvero un'istanza di record attiva). Quell'istanza ha un metodo chiamato attributes, che chiami. Il metodo attributes restituisce un'istanza della classe Hash, che rappresenta i campi nell'istanza record attiva precedente. Hash ha un metodo slice, che si chiama a turno. Il metodo slice restituisce un'altra istanza di Hash, contenente il sottoinsieme di campi specificato.

Quindi, il concetto da chiarire è che quando si concatenano i metodi, non si chiama ogni metodo successivo sulla stessa cosa: lo si chiama sul valore di ritorno del metodo precedente nella catena .

OK, quindi con quella fuori strada:

Tutti i metodi find hanno lo scopo di interrogare il database e restituire una singola istanza di un modello Active Record, o un array di rubino pianura che contiene più istanze di Active Record Modelli.

Un sacco di altri metodi - select, where, ecc. NON colpiscono immediatamente il database e NON intendono restituire un'istanza di record attiva. Tutti restituiscono un'istanza di ActiveRecord::Relation.Un ActiveRecord::Relation è un po 'come un potenziale gruppo di record che soddisfano determinate condizioni - ed è possibile aggiungere ulteriori condizioni ad esso. È come una "query del database in attesa di accadere" o una "query del database che potrebbe essere o non essere ancora avvenuta".

Quando si chiama un metodo come where, order, o select su ActiveRecord::Relation, restituirà un'istanza di ActiveRecord::Relation, il che significa che hai un'istanza della stessa classe, e può metodi di catena da quella classe piacevolmente ad esempio: User.where(name: 'Fred').select(:id, :name).order('name ASC')

l'istanza di ActiveRecord::Relation sarà molto intelligente, e non preoccuparsi di colpire il database fino a quando si chiama un metodo che indica chiaramente si desidera che i record ora - come each, all, take, ecc

Quindi, sono andato più lungo del previsto qui, quindi concluderò. Ecco il codice che ho prima accennato, con un panne, pesantemente commentato spiegazione di seguito:

User.where(id: 5).select(:id, :first_name).take 

scomponendola:

my_relation = User.where(id: 5) 
# The database will not have been hit yet - my_relation 
# is a query waiting to happen 

my_second_relation = my_relation.select(:id, :first_name) 
# The database has STILL not been hit. 
# the relation now contains both the conditions 
# from the previous my_relation, and the new 'select' 
# criteria we specified 

my_user = my_second_relation.take 
# OK, 'take' means we want the first record 
# matching all our criteria, 
# so my_second_relation will hit the database 
# to get it, and then return an Active Record 
# instance (ie, an instance of the User class) 

Wow ... sono andato più a lungo del previsto. Spero che alcuni di essi siano stati utili!

+0

Eccellente ...... – Filippos

+4

Una delle migliori spiegazioni di ActiveRecord :: Relazione che abbia mai letto! Grazie!! – thenextmogul

13

Prova questo:

User.where(id: 5).pluck(:id, :first_name) 

restituisce matrice contenente id e valori first_name

2

Questa volontà funziona così

User.select(:id, :first_name).find(5)

Problemi correlati