2009-01-21 47 views
0

我有以下的ActiveRecord類:如何使用Shoulda測試引用class屬性的named_scope?

class User < ActiveRecord::Base 
    cattr_accessor :current_user 
    has_many :batch_records 
end 

class BatchRecord < ActiveRecord::Base 
    belongs_to :user 

    named_scope :current_user, lambda { 
    { :conditions => { :user_id => User.current_user && User.current_user.id } } 
    } 
end 

,我嘗試使用Shoulda測試named_scope :current_user但下面不工作。

class BatchRecordTest < ActiveSupport::TestCase 
    setup do 
    User.current_user = Factory(:user) 
    end 

    should_have_named_scope :current_user, 
          :conditions => { :assigned_to_id => User.current_user } 
end 

它不工作的原因是因爲被定義的類時,在should_have_named_scope方法User.current_user呼叫正在評估,我在運行時在setup塊改變current_user值之後測試。

這裏是我沒拿出來測試這個named_scope:

class BatchRecordTest < ActiveSupport::TestCase 
    context "with User.current_user set" do 
    setup do 
     mock_user = flexmock('user', :id => 1) 
     flexmock(User).should_receive(:current_user).and_return(mock_user) 
    end 

    should_have_named_scope :current_user, 
          :conditions => { :assigned_to_id => 1 } 
    end 
end 

那麼你會如何測試這個使用Shoulda

回答

1

我認爲你會這樣做是錯誤的。首先,你爲什麼需要使用一個命名範圍?不會這樣做嗎?

class BatchRecord < ActiveRecord::Base 
    belongs_to :user 

    def current_user 
    self.user.class.current_user 
    end 
end 

在這種情況下,它將是微不足道的測試。但! WTF是否將current_user定義爲類屬性?既然Rails 2.2是「線程安全的」,如果你在兩個獨立的線程中運行你的應用程序會發生什麼?一個用戶將登錄,爲ALL User實例設置current_user。現在具有管理權限的另一個用戶登錄並且current_user被切換到他們的實例。當第一位用戶轉到下一頁時,他/她將有權以其管理員權限訪問其他人員帳戶!休克!恐怖!

我推薦在這種情況下做的是要麼新建一個控制器方法current_user它返回當前用戶的用戶實例。你也可以走一步,並創建一個包裝模式,如:

class CurrentUser 

    attr_reader :user, :session 

    def initialize(user, session) 
    @user, @session = user, session 
    end 

    def authenticated? 
    ... 
    end 

    def method_missing(*args) 
    user.send(*args) if authenticated? 
    end 

end 

哦,順便說一句,我現在在你的問題看起來又或許它是不工作的原因之一是該行 User.current_user && User.current_user.id將返回一個布爾值,而不是您想要的整數。 編輯我是個白癡。

命名範圍實際上是這樣做的絕對錯誤的方法。命名範圍意味着返回集合,而不是單個記錄(這是失敗的另一個原因)。它也會導致數據庫不必要的調用,從而導致您不需要的查詢。

+0

Ruby邏輯運算符(&&,||)不符合您的建議。他們返回評估的最後一個參數。因此,如果User.current_user或User.current_user.id是一個布爾值,那麼current_user代碼將只返回一個布爾值 - 我認爲情況並非如此。 – Chuck 2009-01-22 00:36:40

+0

哎呀,你是對的!清晨喝酒沒有幫助我的Ruby技能。 – 2009-01-22 03:25:21

0

我剛剛意識到答案正盯着我。我應該從協會的另一邊工作,這將是current_user.batch_records。然後,我只需在User模型上測試named_scope,一切都很好。

@Chris Lloyd - 關於線程安全問題,current_user屬性正在被before_filter在我ApplicationController設置,所以它每次請求修改。我知道,如果我選擇在多線程環境中運行(目前情況並非如此),仍有可能發生災難。我想這個解決方案完全是另一個話題。

相關問題