2016-11-19 1 views
0

Wenn detect auf einem int-Array durchgeführt wird, funktioniert es:Rails - Wie kann ich die Verwendung der Datenbank während der Ausführung einer Erkennungsmethode vermeiden?

@number = [1,2,3,4,5,6,7].detect{|n| n == 4} 

Variable @number wird 4.

Aber wenn ich etwas tun, wie folgt aus:

@categories = Category.all 
@current_category = @categories.detect{|cat| cat.id == params[:category]} 

Das Programm gibt

Category Load (0.2ms) SELECT "categories".* FROM "categories"

Was bedeutet, dass es die Datenbank verwendet, um es zu finden.

Allerdings ist das Element, das ich versuche zu finden, bereits in der Sammlung @categories, ich möchte es nur finden, um es einer Variablen zuzuordnen.

Natürlich wäre eine andere Lösung, einen linearen Suchalgorithmus zu implementieren, aber ich möchte den Code so sauber wie möglich halten.

Wie kann ich vermeiden, die Datenbank für diese Suche zu verwenden?

EDIT: Ich habe gerade festgestellt, dass dies faul holen könnte. Weil ich vor detect nie @categories benutze, so tut es die Abfrage, wenn ich detect mache. Könnte das wahr sein?

Antwort

1

Rails führt tatsächlich eine SELECT COUNT(*) Abfrage, wenn Sie @categories.all aufrufen, im Wesentlichen eine Lazy-Fetch durchführen.

Ihr @categories Objekt muss noch die Datenbank nach den Daten abfragen.

finden Sie in der Dokumentation hier: http://apidock.com/rails/ActiveRecord/Scoping/Named/ClassMethods/all

posts = Post.all 
posts.size # Fires "select count(*) from posts" and returns the count 
posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects 

fruits = Fruit.all 
fruits = fruits.where(color: 'red') if options[:red_only] 
fruits = fruits.limit(10) if limited? 
+0

Ja Dank ich dachte nur irgendwie heraus, dass dieser fauler fetching sein könnte, weil ich nicht die Daten vor Verwendung erkennen . Aber wenn ich es benutze, verschwindet diese "Extra-Abfrage", danke :) –

0

In Ihrem Fall sollten Sie aktiven Datensatz und SQL verwenden anfordert.

@current_category = @categories.find_by(id: params[:category]) 

Verwendung Array Methoden auf Active Record Beziehungen neigen dazu, alle Daten zu holen dann den Algorithmus in-memory anzuwenden, während SQL Filterung schneller ist.

In Ihrem Fall, den ich liebe die Bediener [] auf meinem Modell zu definieren:

#in category.rb 
def self.[](x) 
    self.find_by(id: x) 
end 

# anywhere after: 
if c = Category[params[:id]] 
    puts "Category found and it's #{c.name} !" 
else 
    puts "Not found :(" 
end 
Verwandte Themen