ARクエリ構造と完全に連携するかなり単純なクエリがあります。
user = User.includes({:network => :product}).joins({:network => :product}).where(:id => user_id).first
これにより、データベースに対して単一のクエリが実行され、熱心にロードされたコレクションにデータが入力されます(つまりuser.product.network.name
、DBに追加のクエリを呼び出さなくても呼び出すことができます)。
User
ユーザーのテーブルに存在しないオブジェクトにいくつかの「疑似」列を追加したいのですが、この最初のクエリの一部としてデータを入力したいと思います。SQLは次のようになります。
SELECT
"users".*,
"networks".*,
"products".*,
(select count("spaces".id) from spaces "spaces" where "spaces".owner_id = "users".id) as spaces_count
FROM
users "users"
JOIN
networks "networks"
on "networks".id = "users".network_id
JOIN products "products"
on "products".id="networks".product_id
WHERE "users".id=?
(最適化されていない)内部クエリでの「spaces_count」列の追加は、この段階での唯一の「pseduo」列ですが、ビューはさらに追加することです。
User
クラス(ActiveRecordモデル)には次のものがあります。
attr_accessible :spaces_count
SQLクエリを実行するために、以下を使用しています。
user = find_by_sql(sql)
ActiveRecord::Associations::Preloader.new([user], {:network => :product}).run
ここで、sqlは上記に含まれるクエリです。
結果は、 「疑似」列User
を含む、予想どおりに入力されたモデルですが、アソシエーションプリローダーの呼び出しの一部として、DBにさらに2回ヒットします。spaces_count
run
1.9.3p125 :465 > ActiveRecord::Associations::Preloader.new([user], {:network => :product}).run
Network Load (0.5ms) SELECT "networks".* FROM "networks" WHERE "networks"."id" IN (1)
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" IN (1)
=> [{:network=>:product}]
ActiveRecord::Associations::Preloader
のように、DBに追加の回数ヒットすることなく、関連付けを熱心にフェッチするために使用する方法はありincludes
ますjoins
か?
Rails 3.2、Ruby 1.9.3-p125、PG9.1を使用しています。