14

背景

深くネストされたアソシエーションを持つレールアプリケーションがあります。アクティブモデルシリアライザとの積極的なロードアソシエーション

      .-< WorkPeriod 
Timecard -< Week -< Day -<--< Subtotal 
          `-< Adjustment 

-< (has many) 

私は、APIを構築するためにActive Model Serializerを使用しています。

クライアント側では、タイムカードとすべての関連付けをワンショットでロードしたいと考えています。何も熱心にロードされ得ない以外

は、現在、私のシリアライザは、

class TimecardSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :weeks 
end 
class WeekSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :days 
end 
# ... etc ... 

問題

このすべての作品が見つけ、このように見えます。したがって、各リクエストごとにデータベースへの呼び出しをたくさん作成することになります。毎週、その週の曜日を別々に要求します。そして、毎日、それはwork_periods、小計、および調整のための別個の要求を行います。

答えて

9

1つの解決方法は、独自のweeksメソッドをTimecardSerializerで定義することです。そこから、.includes()あなたは熱心に負荷をかけたいすべての関連付けをすることができます。

class TimecardSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :weeks 

    def weeks 
    object.weeks.includes(days: [:sub_totals, :work_periods, :adjustments]) 
    end 
end 

すべてのクエリはログに表示されますが、ほとんどのクエリは実際のクエリではなくキャッシュされたクエリになります。

+1

これは単一のリソースを読み込むのには問題ありませんが、このシリアライザを使用して 'Timecard'のリストを返すとうまくいきません。特に、 'weeks'の関連付けは行われますが、' weeks'は熱心に読み込まれません。 – hjdivad

8

私も同様の問題がありました。私は自分のコントローラーで修正しました。私はそれをシリアライザに入れたいと思っていますが、コントローラーにArraySerializerで作成されたn + 1週間の問題もキャッチしています。

Timecard.find(params[:id]).includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

Timecard.includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

今べき熱心な負荷とちょうど6デシベルヒットにクエリを制限します。

関連する問題