我有一个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"]]
答案 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是关于热切加载的好文章。