ActiveRecord: includes: how to use a map with loaded associations?

I have a small rails application and am trying to get order statistics. Therefore, I have an administrator model and an order model with a one-to-many association.

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

And I'm trying to get specific orders using this request:

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

This works as expected. But when I try to make json using such a card,

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

Rails loads orders again using a new request, ignoring objects already loaded.

 (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 

When I try to use a loop instead of a map, it works as it should:

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

this code does not download all orders and prints only those that are loaded in the first request. Is it possible to get the same result using a map? What are the disadvantages of using a loop instead of a map?

+3
source share
1 answer

pluck should always make a new database request. Not sure why you think this is not happening in each loop. Maybe you did not see the magazine, because it is between your prints?

There are 2 ways to avoid additional queries.

  • Since orders are already loaded because you include them, you can do admins.map {|a| [a.name, a.orders.collect(&:operation)]} admins.map {|a| [a.name, a.orders.collect(&:operation)]}

  • Using unions (see @tihom comment).

Edit: I just tested the behavior of each / map , and it reboots every time as expected.

+6
source

Source: https://habr.com/ru/post/954881/


All Articles