2016-11-19 1 views
0

int配列にdetectを実行する場合、それは動作します:Rails - 検出方法の実行中にデータベースを使用しないようにするにはどうすればよいですか?

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

プログラムの出力

:私はこのような何かをするとき

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

変数@numberは4

なるが、

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

これは、データベースを使用して検索することを意味します。

しかし、私が見つけようとしている要素はすでにコレクション@categoriesにあります。変数に割り当てることができます。

もちろん、別の解決策は線形検索アルゴリズムを実装することですが、コードを可能な限りきれいに保ちたいだけです。

この検索で​​データベースを使用しないようにするにはどうすればよいですか?

EDIT:私は、これが怠惰なフェッチである可能性があることを認識しました。 detectの前には@categoriesを使用していないので、detectを実行するとクエリが実行されるためです。これは本当ですか?

答えて

1

@categories.allを呼び出すと、実際にレイジーフェッチを実行すると、Railsは実際にSELECT COUNT(*)というクエリを実行しています。

@categoriesオブジェクトでもデータのクエリをデータベースで行う必要があります。

がここにドキュメントを参照してください:あなたのケースで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

うん感謝:私は私のモデルにオペレータ[]を定義するために愛する場合

。しかし、私はそれを使用すると、この "余分なクエリ"が消えて、感謝:) –

0

を、あなたはアクティブなレコードとSQ​​L要求を使用する必要があります。

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

アクティブレコード関係で配列メソッドを使用すると、すべてのデータがフェッチされ、アルゴリズムがメモリー内に適用される傾向がありますが、SQLフィルタリングは高速です。私が検出する前にデータを使用していないので、私はちょうど種類の、これは遅延フェッチすることができることを考え出し

#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 
関連する問題