2014-11-21 6 views
6

ho visto find metodo di prendere un blocco comeRails trovano con un blocco

Consumer.find do |c| 
    c.id == 3 
end 

che è simile a (3) Consumer.find Rails.

Quali sono alcuni dei casi d'uso in cui possiamo effettivamente utilizzare il blocco per un find?

risposta

12

E 'una scorciatoia per .to_a.find { ... }. Ecco il metodo del source code:

def find(*args) 
    if block_given? 
    to_a.find(*args) { |*block_args| yield(*block_args) } 
    else 
    find_with_ids(*args) 
    end 
end 

Se si passa un blocco, chiama .to_a (caricamento di tutti i record) e invoca Enumerable#find sulla matrice.

In altre parole, consente di utilizzare Enumerable#find su un ActiveRecord::Relation. Questo può essere utile se la tua condizione non può essere espressa o valutata in SQL, ad es. l'interrogazione serialized attributes:

Consumer.find { |c| c.preferences[:foo] == :bar } 

Per evitare confusione, preferisco la versione più esplicito, però:

Consumer.all.to_a.find { |c| c.preferences[:foo] == :bar } 
+0

Ma 'Consumer.to_a' non è definito, è vero? Una classe che eredita da ActiveRecord :: Base non è un'istanza di ActiveRecord :: Relation. –

+0

@Save hai ragione, devi chiamare '.all.to_a'. Avrei dovuto testare il mio codice. – Stefan

4

Il risultato può essere simile, ma la query SQL non è simile a Consumer.find(3)

Si sta raggiungendo tutti i consumatori e quindi filtrando basato sul blocco. Non posso pensare a un caso d'uso in cui questo potrebbe essere utile

Ecco una query di esempio nella console

consumer = Consumer.find {|c|c.id == 2} 
# Consumer Load (0.3ms) SELECT `consumers`.* FROM `consumers` 
# => #<Consumer id: 2, name: "xyz", ..>