我有以下的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_usershould_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,故每个请求修改。据我所知,还有灾难的可能性,如果我选择了在多线程环境中运行(这是目前情况并非如此)。该解决方案我想就完全是另一个主题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top