首先,MyClass.all.some_action 不起作用,因为MyClass#some_action 是一个实例方法,同时MyClass#all 返回一个Array -- 所以当你这样做时MyClass.all.some_action 你实际上是在调用@987654328 @。
另外,请注意 MyClass.all 和 MyClass.active 返回不同的类:
MyClass.active.class # => ActiveRecord::Relation
MyClass.active.all.class # => Array
我不确定您的 some_action 应该做什么...我想您可能想要做的一些选择:
选项 #1:缩小数据库查询范围
如果some_action 正在过滤数组,则应将其转换为另一个作用域,如下所示:
class MyClass < ActiveRecord::Base
scope :active, where(:status => 'active')
scope :inactive, where(:status => 'inactive')
scope :some_action, ->(color_name) { where(color: color_name) }
end
然后使用MyClass.active.some_action('red').all 调用它。如果你只想要第一个结果,MyClass.active.some_action('red').first。
如何使用 RSpec 测试 scope
这是一个很好的答案(以及原因):Testing named scopes with RSpec。
选项 #2:在实例之上执行操作
假设您真的希望将MyClass#some_action 定义为实例方法。然后,您可以尝试这样做:
class MyClass < ActiveRecord::Base
scope :active, where(status: 'active')
scope :inactive, where(status: 'inactive')
def some_action
self.foo = 'bar'
self
end
end
在这种情况下,您可以使用MyClass.active.last.some_action 执行它,因为#last 将返回一个实例,而不是整个数组。
如何使用 RSpec 测试some_action
我认为你应该简单地用期望来测试它:
MyClass.should_receive(:some_action).at_least(:once)
MyClass.active.last.some_action
对此的补充讨论:How to say any_instance should_receive any number of times in RSpec
选项 #3:集体行动
假设您真的想运行MyClass.active.some_action。我建议你先试试这个(与选项 #2 相同的例子):
class MyClass < ActiveRecord::Base
scope :active, where(status: 'active')
scope :inactive, where(status: 'inactive')
def some_action
self.foo = 'bar'
self
end
end
然后使用MyClass.active.all.map{|my_class| my_class.some_action } 运行。
现在,如果您真的想要实现 MyClass.active.some_action -- 您希望在 ActiveRecord::Relation 的所有实例上执行 some_action(我不建议这样做),这样做:
class MyClass < ActiveRecord::Base
scope :active, where(status: 'active')
scope :inactive, where(status: 'inactive')
def some_action
# really do it
end
end
还有……
class ActiveRecord::Relation
# run some_action over all instances
def some_action
to_a.each {|object| object.some_action }.tap { reset }
end
end
再次,我不建议这样做。
如何使用 RSpec 测试 some_action
与选项 #2 相同的情况:
MyClass.should_receive(:some_action).at_least(:once)
MyClass.active.last.some_action
注意:所有代码都使用 Ruby 2.0.0-p0。安装使用,很好玩! :-)