selectEnumerable の Ruby メソッドです。初めて走る時
user.posts.select{|post| post.topic == "x" }
の関連付けのすべてのPostインスタンスがデータベースからメモリにロードされます。具体的には ActiveRecord コレクション オブジェクトに。次に、このコレクションに対して が呼び出され、以外の属性を持つコレクション内のすべてのインスタンスが除外されます。user:postsselectPost:topic"x"
上記の行を 2 回実行しても、データベースは再度クエリされません。これは、既にpostsメモリに読み込まれているためです。
以下のincludesようにすると
user= User.includes(:posts).find(1)
:posts返された各Userインスタンス (この場合、単一のUserwhere :idis )のリレーションを熱心にロードします1。Post上記の前のセクションで説明したように、すべてのインスタンスがメモリにロードされました。
その後、次のようなことをすると
user.posts.where(:topic => "x")
に対して新しいクエリを実行するように Rails に指示していますPost。今回は、 の where と where が のすべてのインスタンスを検索しPostます。インメモリ ARel コレクションの「フィルター」のようには機能しません。:topic"x":user_id:iduserwhere
- 悪い別のクエリを避けたい場合
selectは、メモリ内の結果セットをフィルタリングする良い方法です。
- ベンチマークを実行して、どちらが速いかを見つけることができます。
- データベースにクエリを実行し、別の ARel コレクションをメモリに再設定する
- メモリ内の enumberable を反復処理し、Ruby でフィルターを実行する
に関連するすべてが必要ない場合は、これを元のクエリに簡単に含めることができます:postsuser
user.includes(:posts).where("posts.topic = ?", 'x')