1

1->N->Nの関連付けがあるシナリオ。例:[投稿]->[コメント]->[投票](投票は、コメントに投票した人の名前のリストになります)。インクルードを含むページを表示するには、次のようになります。

@post = Post.where(:id => 100).includes({:comments => :votes}).first

キャッシュサポートを追加し始めています。つまり、コメントの部分がすでにキャッシュされている場合は、コメント/投票を常に含めて実行する必要はありません。したがって、コードを次のように表示する方法があるかどうか疑問に思います。

# controller
@post = Post.find(100)

# view
<% cache('comments', @post.last_comment_time do %>
    <% @post.includes({:comments => :votes}).comments.each do |comment| # ???? %>
<% end %>

「ポストクエリ」インクルードを実行すると、関連付けが「入力」されます。したがって、@ post.commentsが入力され、各コメントにすべての投票が含まれます。これを達成する方法はありますか?

PSビューはクエリを実行するのに最適な場所ではないことを認識しています。これは単なる例です。

4

2 に答える 2

2

allRailsの最新リリースでは、すべてのファインダーメソッドがプロキシオブジェクトを返します。プロキシオブジェクトは、あなたの場合のように、またはfirstあなたの場合のように、イテレーターメソッドを送信するとデータベース呼び出しをトリガーするだけです。これが、のようなすべての呼び出しをチェーンできる理由ですPost.where.order.sort.bla

includesただし、postモデルをロードして、後で呼び出しを使用することはできません。includesモデルインスタンスでロードされるリレーションの呼び出しを使用して機能するjoinため、リレーションごとに1つではなく、データベース呼び出しが1つだけになります。

ビューでactive_recordコードを実行することも悪い習慣です。データの取得は、ビューではなく、コントローラーの責任です。

于 2012-08-06T17:31:35.737 に答える
1

これはかなり古い質問ですが、これは今このように行うことができます

# controller
@post = Post.find(100)

# view
<% cache('comments', @post.last_comment_time do %>
    <% ActiveRecord::Associations::Preloader.new.preload @post, comments: :votes # this will trigger one query %>
    <% @post.comments.each do |comment| # this will not trigger any additional queries %>
<% end %>

最もクリーンな方法ではありませんが、それは仕事をします

于 2015-11-20T18:47:42.180 に答える