Ich habe eine Rails-App, wo ich oft xls-Dateien mit mehreren Werten generieren muss. Dazu ich Kunden Aufträge in meinem Controller laden (valid
ist nur ein benutzerdefinierter Bereich)Rails - Zählschleife mit Active Record
@orders = Order.valid.order('id DESC')
Meiner Ansicht nach, ich mag mit verschiedenen Bereichen für die einzelnen Aufträge Mahlzeiten zählen (i entfernt alle XML-Tags, die sind nicht interessant hier):
<% @orders.each do |order| %>
<%= order.meals.count %>
<%= order.meals.meat.count %>
<%= order.meals.fish.count %>
<%= order.meals.drink.count %>
<%= order.meals.dessert.count %>
<% end %>
Mein Problem ist, dass dies eine sehr große Anzahl von SQL-Anfragen generiert.
Ich habe versucht, Mahlzeiten wie diese vorab zu laden:
@orders = Order.valid.order('id DESC').preload(:meals)
Aber Anfragen
auch ein altes Juwel erzeugt werden, halten zählenich gefunden: preload_count
, dies zu tun, aber es mit Schienen nicht funktioniert nicht 4 .
Gibt es eine Möglichkeit, meine Anfragen zu optimieren?
EDIT
Nach vielen Versuchen und Hilfe von Andrey Dejneko, meine Anfrage in diese gedreht:
Order.includes(:meals).valid.order('id DESC').references(:meals)
Dann ist es mir klar, kann aus Mahlzeit Arten kommen, die in meinem DB in einer anderen Tabelle sind
Order.eager_load(meals: :type).valid.order('orders.id DESC').references(:meals)
Aber immer noch, hier sind meine db Anfragen:
(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"]]
Beim Iterieren von Sammlungen sollten Sie 'find_each' verwenden, das in Stapelform statt" each "eingefügt wird, um zu verhindern, dass eine potenziell massive Ergebnismenge in den Speicher geladen wird. –
Danke, ich habe das in meinem Code geändert, aber es beantwortet meine Frage nicht:/ – Shrolox