2 つのモデル (Rails 2.3.8):
- ユーザー; ユーザー名と無効なプロパティ; ユーザー has_one :プロファイル
- プロフィール; full_name と隠しプロパティ
disabled=1 および hidden=1 のユーザー プロファイルを排除する named_scope を作成しようとしています。User モデルは通常、Profile モデルと組み合わせて使用されるため、Profile モデル (:include => :profile) をeager-loadしようとします。
User モデルに「visible」という名前の named_scope を作成しました。
named_scope :visible, {
:joins => "INNER JOIN profiles ON users.id=profiles.user_id",
:conditions => ["users.disabled = ? AND profiles.hidden = ?", false, false]
}
クエリで named_scope を使用すると、eager-loading 命令が無視されることに気付きました。
バリエーション 1 - ユーザー モデルのみ:
# UserController
@users = User.find(:all)
# User's Index view
<% for user in @users %>
<p><%= user.username %></p>
<% end %>
# generates a single query:
SELECT * FROM `users`
バリエーション 2 - ビューでプロファイル モデルを使用します。遅延ロード プロファイル モデル
# UserController
@users = User.find(:all)
# User's Index view
<% for user in @users %>
<p><%= user.username %></p>
<p><%= user.profile.full_name %></p>
<% end %>
# generates multiple queries:
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 1) ORDER BY full_name ASC LIMIT 1
SHOW FIELDS FROM `profiles`
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 2) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 3) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 5) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 6) ORDER BY full_name ASC LIMIT 1
バリエーション 3 - 熱心なロード プロファイル モデル
# UserController
@users = User.find(:all, :include => :profile)
#view; no changes
# two queries
SELECT * FROM `users`
SELECT `profiles`.* FROM `profiles` WHERE (`profiles`.user_id IN (1,2,3,4,5,6))
バリエーション 4 - 熱心な読み込み命令を含む name_scope を使用する
#UserConroller
@users = User.visible(:include => :profile)
#view; no changes
# generates multiple queries
SELECT `users`.* FROM `users` INNER JOIN profiles ON users.id=profiles.user_id WHERE (users.disabled = 0 AND profiles.hidden = 0)
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 1) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 2) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 3) ORDER BY full_name ASC LIMIT 1
SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) ORDER BY full_name ASC LIMIT 1
バリエーション 4 は正しい数のレコードを返しますが、eager-loading 命令を無視しているようにも見えます。
これはクロスモデルの名前付きスコープの問題ですか? おそらく私はそれを正しく使用していません。
この種の状況は、Rails 3 でより適切に処理されますか?