如何使用 Shoulda 测试引用类属性的named_scope?
我有以下 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 “Shoulda">Shoulda 但以下不起作用。
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
的调用,并且我要更改运行测试时,将 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
那么你如何使用 Shoulda< 来测试它/a>?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你处理这个问题的方式是错误的。 首先,为什么需要使用命名范围? 这不行吗?
在这种情况下,测试就很简单了。 但! WTF 你将
current_user
定义为类属性吗? 既然 Rails 2.2 是“线程安全的”,如果您在两个单独的线程中运行应用程序会发生什么? 一名用户登录,为所有User
实例设置current_user
。 现在,另一个具有管理员权限的用户登录,current_user
已切换到其实例。 当第一个用户进入下一页时,他/她将可以使用管理员权限访问其他人的帐户! 震惊! 恐怖!在这种情况下,我建议做的是创建一个新的控制器方法
current_user
,它返回当前用户的 User 实例。 您还可以更进一步,创建一个包装器模型,例如:哦,顺便说一句,现在我再次查看您的问题,也许它不起作用的原因之一是行编辑 我是个白痴。User.当前用户&& User.current_user.id
将返回一个布尔值,而不是您想要的整数。命名范围实际上是绝对错误的做法。 命名范围旨在返回集合,而不是单个记录(这是失败的另一个原因)。 它还对数据库进行不必要的调用,从而导致您不需要的查询。
I think you are going about this the wrong way. Firstly, why do you need to use a named scope? Wont this just do?
In which case it would be trivial to test. BUT! WTF are you defining
current_user
as a class attribute? Now that Rails 2.2 is "threadsafe" what would happen if you were running your app in two seperate threads? One user would login, setting thecurrent_user
for ALLUser
instances. Now another user with admin privileges logs in andcurrent_user
is switched to their instance. When the first user goes to the next page he/she will have access to the other persons account with their admin privileges! Shock! Horror!What I reccomend doing in this case is to either making a new controller method
current_user
which returns the current user's User instance. You can also go one step further and create a wrapper model like:Oh, and by the way, now I look at your question again perhaps one of the reasons it isn't working is that the lineEDIT I'm an idiot.User.current_user && User.current_user.id
will return a boolean, rather than the Integer you want it to.Named scope is really the absolutely wrong way of doing this. Named scope is meant to return collections, rather than individual records (which is another reason this fails). It is also making an unnecessary call the the DB resulting in a query that you don't need.
我刚刚意识到答案就在盯着我。 我应该在关联的另一端(
current_user.batch_records
)工作。 然后我简单地在User
模型上测试named_scope
,一切都很好。@Chris Lloyd - 关于线程安全问题,
current_user
属性由我的ApplicationController
中的before_filter
,因此它会根据请求进行修改。 我知道如果我选择在多线程环境中运行(目前情况并非如此),仍然有可能发生灾难。 我想这个解决方案将完全是另一个话题。I just realized the answer is staring right at me. I should be working from the other side of the association which would be
current_user.batch_records
. Then I simply test thenamed_scope
on theUser
model and everything is fine.@Chris Lloyd - Regarding the thread safety issue, the
current_user
attribute is being set by abefore_filter
in myApplicationController
, so it is modified per request. I understand that there is still the potential for disaster if I chose to run in a multi-threaded environment (which is currently not the case). That solution I suppose would be another topic entirely.