具体例
例えば、CustomerテーブルとTelephoneテーブルがあり1つのCustomerがN個Telephoneテーブルを持つとする。
Customer一覧でそのCustomerが持ってる全てのTelephoneのtelカラムを一覧でカンマ区切りで表示したい場面があった時に
customers_controller.rb
def index
@customers = Customer.includes(:telephones)
end
customers/index.html.slim
- @customers.each do |customer|
= customer.telephones.pluck(:tel).join(', ')
とすると、コントローラーでincludesしてeager loadingしているにも関わらずN+1になる。
原因
pluckメソッドがSQLのselect文を発行するため。
そのため、Viewでループでcustomerのtelを参照するたびにselect文が発行されてN+1のクエリになります。
対策
pluck(:tel)
を map(&:tel)
に変える。それにより、本来の事前にロードされたtelephonesのtelを見るようになるため N+1を回避できます。
しっかりpluckメソッドの動きを把握すればハマらない問題でした。