2014-11-21 4 views
6

Ich habe gesehen, Rails find Methode einen Block alsRails finden mit einem Block

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

Schritte, die zu Consumer.find ähnlich ist (3).

Was sind einige der Anwendungsfälle, in denen wir tatsächlich Block für eine find verwenden können?

Antwort

12

Es ist eine Abkürzung für .to_a.find { ... } nützlich sein könnte. Hier ist die Methode des source code:

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

Wenn Sie einen Block übergeben, ruft es .to_a (Laden aller Datensätze) und ruft Enumerable#find auf dem Array.

Mit anderen Worten, ermöglicht es Ihnen, Enumerable#find auf einem ActiveRecord::Relation zu verwenden. Dies kann nützlich sein, wenn Ihre Bedingung nicht in SQL ausgedrückt oder ausgewertet werden kann, z. serialized attributes Abfrage:

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

Um Verwirrung zu vermeiden, würde ich die explizitere Version bevorzugen, aber:

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

Aber 'Consumer.to_a' nicht definiert ist, ist es? Eine Klasse, die von ActiveRecord :: Base erbt, ist keine Instanz von ActiveRecord :: Relation. –

+0

@Da hast du recht, du musst '.all.to_a' anrufen. Ich hätte meinen Code testen sollen. – Stefan

4

Das Ergebnis kann ähnlich sein, aber die SQL-Abfrage ist nicht vergleichbar mit Consumer.find(3)

es alle Verbraucher abruft und dann basierend Filterung auf dem Block. Ich kann nicht von einem Anwendungsfall denken, wo diese

Hier ist eine Beispielabfrage in der Konsole

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