如何测试named_scope引用与早该类属性?
-
19-08-2019 - |
题
我有以下的ActiveRecord类:
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
和我想要测试使用早该的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
当正在定义的类和我运行测试时后来更改User.current_user
块should_have_named_scope
的值它不工作时,因为该呼叫到在current_user
方法setup
其原因被评价。
下面是我想出测试这个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
所以,你会如何测试这个使用早该?
解决方案
我想你会对此错误的方式。首先,为什么你需要使用一个名为范围是什么?不会这只是做?
class BatchRecord < ActiveRecord::Base
belongs_to :user
def current_user
self.user.class.current_user
end
end
在这种情况下,这将是微不足道的测试。但!跆拳道是你定义current_user
作为一个类的属性?现在,Rails的2.2“线程”,如果你是在两个不同的线程上运行你的应用程序会发生什么?一个用户会登录,设置current_user
为所有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
会返回一个布尔值,而不是整数,你想要它。击> 修改强>我是白痴。
命名范围确实是这样做的完全错误的方式。命名的范围是指返回集合,而不是单独的记录(这是另一个原因失败)。它也进行不必要的调用数据库导致在你不需要的查询。
其他提示
我刚刚意识到的答案是正确的盯着我。我应该从哪个会current_user.batch_records
协会的另一边进行工作。然后我简单地测试在named_scope
模型User
,一切都很好。
@ 克里斯劳埃德 - 关于线程安全问题,current_user
属性是由在before_filter
设置我ApplicationController
,故每个请求修改。据我所知,还有灾难的可能性,如果我选择了在多线程环境中运行(这是目前情况并非如此)。该解决方案我想就完全是另一个主题。