Upgrade to Pro — share decks privately, control downloads, hide ads and more …

N+1 問題の解決と computed_model

gedorinku
October 05, 2023

N+1 問題の解決と computed_model

gedorinku

October 05, 2023
Tweet

More Decks by gedorinku

Other Decks in Programming

Transcript

  1. 加工した値を返すモデルのメソッド class User < ApplicationRecord has_many :work_experiences # => "ウォンテッドリー株式会社

    / エンジニア" def position_description work_experience = work_experiences.max_by { _1.started_at } "#{work_experience.company_name} / #{work_experience.position}" end end © 2023 Wantedly, Inc.
  2. Preload と N+1 問題 class User < ApplicationRecord has_many :work_experiences

    … end User.where(...).map(&:position_description) User.preload(:work_experiences).where(...).map(&:position_description) © 2023 Wantedly, Inc.
  3. computed_model による解決方法 class User define_primary_loader :raw_user do ... end define_loader

    :work_experiences do ... end dependency :work_experiences computed def position_description work_experience = work_experiences.max_by { _1.started_at } "#{work_experience.company_name} / #{work_experience.position}" end end © 2023 Wantedly, Inc. 依存関係をここに書く ここに書かれていないものを使うと エラーになる
  4. Active Record をデータソースとして使う例 class User define_primary_loader :raw_user do |_, ids:,

    **| RawUser.where(id: ids).map do |raw_user| User.new(raw_user) end end define_loader :work_experiences do ... end end © 2023 Wantedly, Inc.
  5. 他サービスの API をデータソースとして使う例 class User define_primary_loader :raw_user do ... end

    define_loader :work_experiences, key: -> { id } do |user_ids, _, **| WorkExperienceApiClient.list(user_ids: user_ids).group_by(&:user_id) end end © 2023 Wantedly, Inc.