我们有一个相当简单的查询,它与 AR 查询结构完美配合:
user = User.includes({:network => :product}).joins({:network => :product}).where(:id => user_id).first
这将在数据库上执行单个查询,填充急切加载的集合(即:我可以user.product.network.name
在不调用数据库的其他查询的情况下调用)。
我们想向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
模型,按预期填充,包括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
用来急切地获取关联,而无需额外多次访问数据库,按照它的方式includes
吗joins
?
我们正在使用 Rails 3.2、Ruby 1.9.3-p125 和 PG 9.1。