Ruby on rails 优化Rails中的即时加载

Ruby on rails 优化Rails中的即时加载,ruby-on-rails,activerecord,eager-loading,Ruby On Rails,Activerecord,Eager Loading,轨道3.2。我有以下资料: # city.rb class City < ActiveRecord::Base has_many :zones, :dependent => :destroy end # zone.rb class Zone < ActiveRecord::Base belongs_to :city has_many :zone_shops, :dependent => :destroy has_many :shops, :through

轨道3.2。我有以下资料:

# city.rb
class City < ActiveRecord::Base
  has_many :zones, :dependent => :destroy
end

# zone.rb
class Zone < ActiveRecord::Base
  belongs_to :city
  has_many :zone_shops, :dependent => :destroy
  has_many :shops, :through => :zone_shops
end

# zone_shop.rb
class ZoneShop < ActiveRecord::Base
  belongs_to :zone
  belongs_to :shop
end

# shop.rb
class Shop < ActiveRecord::Base
end

# cities_controller.rb
def show
  @trip = City.find(params[:id], :include => [:user, :zones => [:shops]])
  @zones = @trip.zones.order("position")

  # List out all shops for the trip
  shops_list_array = []
  @zones.each do |zone, i|
    zone.shops.each do |shop|
      shops_list_array << shop.name
    end
  end
  @shops_list = shops_list_array.join(', ')
end

# development.log
  City Load (0.3ms)  SELECT `cities`.* FROM `cities` WHERE `cities`.`id` = 1 LIMIT 1
  Zone Load (0.3ms)  SELECT `zones`.* FROM `zones` WHERE `zones`.`trip_id` IN (1) ORDER BY position asc
  ZoneShop Load (0.3ms)  SELECT `zone_shops`.* FROM `zone_shops` WHERE `zone_shops`.`zone_id` IN (26, 23, 22) ORDER BY position asc
  Shop Load (0.5ms)  SELECT `shops`.* FROM `shops` WHERE `shops`.`id` IN (8, 7, 1, 9)
  Zone Load (0.5ms)  SELECT `zones`.* FROM `zones` WHERE `zones`.`trip_id` = 1 ORDER BY position asc, position
  Shop Load (0.5ms)  SELECT `shops`.* FROM `shops` INNER JOIN `zone_shops` ON `shops`.`id` = `zone_shops`.`spot_id` WHERE `zone_shops`.`zone_id` = 26
  Shop Load (0.6ms)  SELECT `shops`.* FROM `shops` INNER JOIN `zone_shops` ON `shops`.`id` = `zone_shops`.`spot_id` WHERE `zone_shops`.`zone_id` = 23
  Shop Load (0.4ms)  SELECT `shops`.* FROM `shops` INNER JOIN `zone_shops` ON `shops`.`id` = `zone_shops`.`spot_id` WHERE `zone_shops`.`zone_id` = 22
请注意,在我的日志中,ID为26、23、22的店铺的最后3行是多余的。我应该如何重写cities_controller.rb以减少对系统的查询

非常感谢。

我建议

zone.shops.each do |shop|
  shops_list_array << shop.name
end
解决方案取决于您的需要,但我建议您阅读Rails的急切加载特性的所有内容。这正是你的问题:每一件事都是如此。在这里查找:

它非常简单、简短、直截了当:

@zones = @trip.zones.includes(:shops).order("position")
这将加载shops关联,并应避免由zone.shops.each引起的n+1查询问题


更多信息,请看一下,这也是由@Benjamin M

链接的。是的,我知道是每一行给了我问题。但我想知道是否有其他方法来编写它,这样就不需要生成最后3行了。因为你会看到前面已经询问过商店了。对不起,我误解了你的问题。但也许这就是你的解决方案:。。。看起来像是迫不及待地加载了很多东西:有时不得不显式地强制加入以正确工作;顺便说一句:include=>。。。[:shops]]您正在使用的不会有帮助,因为include的作用域是@trip,但您正在@zones中循环,您没有应用includes,因为您的解决方案为:ZoneShop Load 0.3ms SELECT zone_shops创建缓存版本。*来自zone_shops,其中zone_shops.zone_id位于26、23中,22按位置asc和车间装载0.5ms订购选择车间。*从8、7、1、9中的shops.id所在的车间中选择,这可以正常工作。只是一个问题,是否有可能完全消除缓存?简单地说:@trip=City.findparams[:id]和@zones=@trip.zones.includes:shops.orderposition。其余的可以保持不变。在使用@trip之前,您可能需要检查它是否为零。
@zones = @trip.zones.includes(:shops).order("position")