Как стремиться загрузить ассоциации с current_user? - PullRequest
15 голосов
/ 01 августа 2011

Я использую Devise для аутентификации в своем приложении Rails.Я хотел бы загрузить некоторые из моделей, связанных с пользователями в некоторых из моих контроллеров.Примерно так:

class TeamsController < ApplicationController

  def show
    @team = Team.includes(:members).find params[:id]
    current_user.includes(:saved_listings)

    # normal controller stuff
  end
end

Как мне этого добиться?

Ответы [ 4 ]

21 голосов
/ 15 ноября 2011

Я столкнулся с той же проблемой, и, хотя все продолжают говорить, что в этом нет необходимости, я обнаружил, что есть, как и вы.Так что это работает для меня:

# in application_controller.rb:
def current_user
  @current_user ||= super && User.includes(:saved_listings).find(@current_user.id)
end

Обратите внимание, что это загрузит ассоциации в всех контроллерах.Для моего случая использования это именно то, что мне нужно.Если вы действительно хотите, чтобы это было только в некоторых контроллерах, вам придется настроить это еще раз.

Это также дважды вызовет User.find, но с кэшированием запросов, которое не должно бытьпроблема, и, поскольку она предотвращает ряд дополнительных обращений к БД, она все равно дает прирост производительности.

9 голосов
/ 08 июня 2016

Переопределить serialize_from_session в вашей User модели.

class User
  devise :database_authenticatable

  def self.serialize_from_session key, salt
    record = where(id: key).eager_load(:saved_listings, roles: :accounts).first
    record if record && record.authenticatable_salt == salt
  end
end

Это, однако, приведет к загрузке всех запросов.

1 голос
/ 18 июня 2019

Я хотел бы добавить то, что я считаю лучшим решением.Как отмечено в комментариях, существующие решения могут дважды поразить вашу БД с помощью запроса find.Вместо этого мы можем использовать ActiveRecord::Associations::Preloader, чтобы усилить работу Rails вокруг ассоциаций загрузки:

def current_user
  @current_user ||= super.tap do |user|
    ::ActiveRecord::Associations::Preloader.new.preload(user, :saved_listings)
  end
end

Это позволит повторно использовать существующую модель в памяти вместо того, чтобы снова соединять и запрашивать всю таблицу.

0 голосов
/ 25 марта 2014

Почему бы не сделать это с default_scope на модели?

примерно так:

Class User  < ActiveRecord::Base
  ...
  default_scope includes(:saved_listings)
  ...
end
...