首先,MyClass.all.some_action
is not going to work since MyClass#some_action
is an instance method,同时MyClass#all
返回一个Array
-- 所以当你这样做时,MyClass.all.some_action
你实际上是在调用Array#some_action
.
另外,注意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
.
如何scope
使用 RSpec进行测试
这是一个很好的答案(以及原因):使用 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
将返回一个实例,而不是整个数组。
如何some_action
使用 RSpec进行测试
我相信你应该简单地用期望来测试它:
MyClass.should_receive(:some_action).at_least(:once)
MyClass.active.last.some_action
对此的补充讨论:How to say any_instance should_receive any numbered 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
——你想some_action
在 ActiveRecord::Relation 的所有实例上执行(我不推荐),这样做:
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
同样,我不建议这样做。
如何some_action
使用 RSpec进行测试
与选项 #2 相同的情况:
MyClass.should_receive(:some_action).at_least(:once)
MyClass.active.last.some_action
注意:所有代码都使用 Ruby 2.0.0-p0。安装使用,很好玩!:-)