N + 1 проблема для пользовательского метода в рельсах - PullRequest
0 голосов
/ 29 октября 2018

в моем приложении rails у меня есть модель User с методом price_tier:

def price_tier
  Spree::PriceTier.by_code[read_attribute(:price_tier)]
end

Однако, когда у меня есть коллекция @users и я вызываю price_tier один за другим, он будет загружать PriceTier запрос для каждого экземпляра, что вызывает проблему N + 1.

includes здесь не работает, поскольку не является ассоциацией.

@users.map { |user| user.price_tier }

Есть ли способ изменить код, исправляющий проблему N + 1?

1 Ответ

0 голосов
/ 29 октября 2018

Вы действительно должны установить отношения между моделями напрямую, например, user has_one :price_tier. Это сделает код здесь легким.

Если вы этого не сделаете, вы прыгаете через обручи для чего-то, что должно быть простым. Вы можете возможно использовать что-то вроде следующего, хотя это все равно будет гораздо менее эффективным, чем прямые отношения:

tiers = Spree::PriceTier.where(code: @users.pluck(:price_tier))
                        .each_with_object({}) { |tier, hash| hash[tier[code]] = tier }

@users.map { |user| tiers[user.price_tier] }

N.B. В приведенном выше примере предполагается удаление метода экземпляра :price_tier и использование атрибута.

Я не уверен, что действительно стоит включить вышеперечисленное - вы собираете пользовательский price_tier, нажимаете db (только один раз, а не для каждого пользователя) для уровней, итерируете их все, чтобы создать хэш для быстрого доступа , затем переберите пользователей, чтобы отобразить их. Это большая работа для чего-то, что легко решается установлением отношений.

Надеюсь, что это поможет, и действительно надеюсь, что тональность в вышеприведенном выражении будет хорошей - в основном это означает, что вы могли бы сделать что-то подобное выше, хотя реальный совет был бы: пожалуйста, не устанавливайте отношения и работать с традиционным подходом здесь:)

...