0

私のアクションは、データベースから取得するインスタンス変数@websitesを設定します。

@websites = Website.all

をスピンしてみる@websitesと、データベースへの呼び出しが 1 つしかないことがわかります。幸せな日々。

<% @websites.each do |website| %>
...
<% end %>

これにより、次の結果が得られます。

Website Load (0.1ms) SELECT "websites".* FROM "websites"   

しかし、次のようにラップするとpresent?:

<% if @websites.present? %>
   <% @websites.each do |website| %>
   <% end %>
<% else %>

今、私は2つのデータベース呼び出しを受け取ります

(0.2ms)  SELECT COUNT(*) FROM "websites"
Website Load (0.1ms) SELECT "websites".* FROM "websites" 

2 つのデータベース呼び出しが行われているのはなぜですか? また、2 番目の呼び出しを停止するにはどうすればよいですか。

私にとって、@websites変数にはすべてのWebサイトがメモリに含まれています。確かにレールは、データベースで新しい SELECT を実行するのではなく、メモリ内のアイテムをカウントするだけでしょうか?

4

1 に答える 1

1

このメソッド呼び出し、

@websites = Website.all

レコードをすぐにメモリにロードしません。それは単なるアクティブなレコード関係です。このリレーションで行う最初の操作はpresent?and を呼び出すことであり、この要求を満たすために、Rails はすべてのレコードをメモリにロードする必要はありません。したがって、ActiveRelation はリレーションを最適化し、カウント クエリを実行して結果を取得します。each メソッドを使用してアクセスした場合にのみ@websites、レコードがロードされます。

その余分なクエリを避けたい場合は、関係を配列に変換できますが、

@websites = Website.all.to_a

これにより、レコードがロードされ、 のArray代わりに がレンダリングされActiveRelationます。しかし、問題は Active リレーションがこのリレーションでさらにクエリをチェーンできないことです。しかし、あなたの状況ではそれは必要ないと思います。

于 2012-11-18T18:32:41.710 に答える