11

我正在使用Devise在我的Rails應用程序中進行身份驗證。我想在我的一些控制器中加載一些與用戶相關的模型。就像這樣:如何加載與current_user的關聯?

class TeamsController < ApplicationController 

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

    # normal controller stuff 
    end 
end 

我該如何做到這一點?

+0

覆蓋current_user方法 – apneadiving

回答

19

我遇到了同樣的問題,雖然每個人都說不需要這樣做,但我發現,就像你一樣。因此,這對我的作品:

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

注意,這將載入協會所有控制器。對於我的用例,這正是我需要的。如果你真的只想在控制器中使用控制器,那麼你將不得不調整更多。

這也將調用User.find兩次,但查詢緩存,不應該是一個問題,而且因爲它可以防止一些額外的DB的命中,它仍然是一個性能增益。

+0

我還沒有測試過,但對我來說看起來不錯。很容易讓這個接受一個參數來代表一個包含表名的數組。 –

+0

請注意,自從Rails 4以來,這個答案使用'#find' _does_觸發''users'上的兩個單獨的數據庫查詢。 '#first'的實現(由['OrmAdapter :: ActiveRecord#get']使用](https://github.com/ianwhite/orm_adapter/blob/v0.5.0/lib/orm_adapter/adapters/active_record.rb#L15 -L18),在Rails 4+中Devise調用序列化其'current_user'對象)添加了'ORDER BY users.id ASC'子句,而'#find'沒有,因此這兩個查詢在查詢緩存中不再匹配。 'User.includes(:saved_listings).where(id:@ current_user.id).first'將跨Rails版本匹配。 – wjordan

0

爲什麼不在模型上用default_scope做到這一點?

像這樣:

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

然後,每個對'User'的查詢都會急切地加載保存的列表(包含測試)。如果你只想加載一個或兩個動作,並且會對應用程序的響應時間和測試套件的速度產生負面影響,那麼這太過分了。 –

+0

只是一個想法......如果你的'current_user'屬於一個公司以及表中的所有其他用戶,並且如果你經常引用返回的用戶或current_user的公司屬性,那麼有沒有這個意義?另外,Rails 4.2.1(不知道以前的版本)不允許沒有塊的'default_scope',所以你必須調用'default_scope {includes(:company)}' – kobaltz

4

覆蓋serialize_from_sessionUser模型。

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 

這將然而,急於負荷所有請求。

相關問題