4

我有一个小型 Rails 应用程序,我正在尝试获取一些订单统计信息。所以我有一个 Admin 模型和一个 Order 模型,具有一对多关联。

class Admin < ActiveRecord::Base
  attr_accessible :name
  has_many :orders
class Order < ActiveRecord::Base
  attr_accessible :operation
  belongs_to :admin

我正在尝试使用此查询获取特定订单:

admins = Admin.where(...).includes(:orders).where('orders.operation = ?', 'new gifts!')

这正如预期的那样工作。但是当我尝试使用这样的地图制作json时

admins.map {|a| [a.name, a.orders.pluck(:operation)]}

Rails 使用新查询再次加载订单,忽略已加载的对象。

(5.6ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 26
(6.8ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 24
(2.9ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 30
(3.3ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 29
(4.8ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 27
(3.3ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 28
(5.1ms)  SELECT "orders"."operation" FROM "orders" WHERE "orders"."admin_id" = 25

当我尝试使用循环而不是地图时,它可以正常工作:

admins.each do |a|
  p a.orders.pluck(:operation)
end

此代码不会加载所有订单,并且仅打印在第一个查询中加载的那些。是否可以使用地图获得相同的结果?使用循环而不是地图有什么缺点?

4

1 回答 1

7

pluck应始终对数据库进行新查询。不知道为什么你认为它不会each循环发生。也许您没有看到日志,因为它在您的打印之间?

有 2 种可能性如何避免额外的查询。

  1. 由于订单已经加载,因为您包含它们,您可以执行admins.map {|a| [a.name, a.orders.collect(&:operation)]}

  2. 使用连接(参见@tihom 的评论)。

编辑:我刚刚测试了each/map行为,它每次都按预期重新加载。

于 2013-09-30T19:11:36.413 回答