2

レール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

logの中で、ID 26、23、22のショップの最後の3行は冗長であることに注意してください。cities_controller.rbシステムへのクエリを減らすために、どのように書き直す必要がありますか?

どうもありがとう。

4

2 に答える 2

2
@zones = @trip.zones.includes(:shops).order("position")

これにより、ショップの関連付けが熱心に読み込まれ、n+1 クエリの問題が解消されます。zone.shops.each

詳細については、@Benjamin M によってリンクされた Eager Loading associations に関する Ruby on Rails ガイドのセクション 12 を参照してください。

于 2013-02-27T16:19:14.807 に答える
0

私はこれをお勧めします

zone.shops.each do |shop|
  shops_list_array << shop.name
end

ログの最後の 3 行を生成します。これは、現在、データベース内に 1 つしかないことを意味zoneします。そこにさらに多くのゾーンを配置するとZone Load、ログにさらに多くのエントリが記録されます。

問題は明らかに、遅延読み込みをトリガーする Rails のeach方法です。

@zones.each do |zone, i|
  ...

解決策はニーズによって異なりますが、Rails の熱心な読み込み機能に関するすべてを読むことをお勧めします。(まさにあなたの問題があります:each事)。ここで調べてください: http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

とても簡単で、短くて簡単です:)

于 2013-02-27T15:45:30.293 に答える