How to eager load associations with the current_user?

。_饼干妹妹 提交于 2019-12-04 16:34:14

问题


I'm using Devise for authentication in my Rails app. I'd like to eager load some of a users associated models in some of my controllers. Something like this:

class TeamsController < ApplicationController

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

    # normal controller stuff
  end
end

How can I achieve this?


回答1:


I ran into the same issue and although everyone keeps saying there's no need to do this, I found that there is, just like you. So this works for me:

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

Note that this will load the associations in all controllers. For my use case, that's exactly what I need. If you really want it only in some controllers, you'll have to tweak this some more.

This will also call User.find twice, but with query caching that shouldn't be a problem, and since it prevents a number of additional DB hits, it still is a performance gain.




回答2:


Override serialize_from_session in your User model.

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

This will however, eager load on all requests.




回答3:


I wanted to add what I think is a better solution. As noted in comments, existing solutions may hit your DB twice with the find request. Instead, we can use ActiveRecord::Associations::Preloader to leverage Rails' work around loading associations:

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

This will re-use the existing model in memory instead of joining and querying the entire table again.




回答4:


Why not do it with default_scope on the model?

like so:

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


来源:https://stackoverflow.com/questions/6902531/how-to-eager-load-associations-with-the-current-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!