Rails - 使用Active Record计算循环

时间:2016-04-08 16:15:38

标签: ruby-on-rails ruby-on-rails-4 activerecord

我有一个rails应用程序,我经常需要生成具有多个值的xls文件。 为此,我在控制器中加载客户订单(valid只是一个自定义范围)

@orders = Order.valid.order('id DESC')

在我看来,我想为不同范围的每个订单计算膳食(我删除了所有xml标签,这里不感兴趣):

<% @orders.each do |order| %>
  <%= order.meals.count %>
  <%= order.meals.meat.count %>
  <%= order.meals.fish.count %>
  <%= order.meals.drink.count %>
  <%= order.meals.dessert.count %>
<% end %>

我的问题是这会产生大量的SQL请求。

我试着预装这样的饭菜:

@orders = Order.valid.order('id DESC').preload(:meals)

但计数请求一直在生成

我还找到了一个旧宝石:preload_count来做这件事,但它不适用于rails 4.

有没有办法优化我的请求?

修改

经过安德烈·迪内科的多次尝试和帮助后,我的要求转变为:

Order.includes(:meals).valid.order('id DESC').references(:meals)

然后我意识到它可能来自我的数据库中另一个表中的膳食类型

Order.eager_load(meals: :type).valid.order('orders.id DESC').references(:meals)

但是,这仍然是我的数据库请求:

(0.3ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1  [["order_id", 1044]]
   (0.3ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1  [["order_id", 1044]]
   (0.4ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "meat"]]
   (0.4ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "meat"]]
   (0.4ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "fish"]]
   (0.4ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "fish"]]
   (0.3ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "drink"]]
   (0.3ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "drink"]]
   (0.3ms)  SELECT COUNT(*) FROM "meals" INNER JOIN "types" ON "types"."id" = "meals"."type_id" INNER JOIN "meals_orders" ON "meals"."id" = "meals_orders"."meal_id" WHERE "meals_orders"."order_id" = $1 AND "types"."name" = $2  [["order_id", 1044], ["name", "dessert"]]

2 个答案:

答案 0 :(得分:1)

跟着

@orders = Order.includes(:meals).valid.order('id DESC')

如果您只想订餐(没有订单,餐点是nil),请选择:

@orders = Order.joins(:meals).valid.order('id DESC')

阅读AR querying

答案 1 :(得分:0)

如果您的模型具有has_many belongs_to关系,则可以使用includes来急切加载关联。 This是关于热切加载的好文章。