根据Rails documentation for scope
,范围如:
class Shirt < ActiveRecord::Base
scope :red, -> { where(color: 'red') }
end
是真的:
class Shirt < ActiveRecord::Base
def self.red
where(color: 'red')
end
end
他们还说该关系应该充当Array
,所以做这样的事情
Shirt.red.each(&block)
应该有效......而且确实如此。
使用我们上面所知的一切,为什么以下不起作用?
class Shirt < ActiveRecord::Base
def self.short_sleeved
reject{|object| object.short_sleeved == false}
end
end
Shirt.red.short_sleeved
会产生undefined method 'reject' for #<Class:0xba552d4>
答案 0 :(得分:1)
您无法按照您尝试的方式定义short_sleeved
方法,因为ActiveRecord类不是ActiveRecord关系。
您在short_sleeved
上定义了Shirt
。 Shirt
是ActiveRecord模型类。它本身不是ActiveRecord关系。它有一些方法,包括all
和where
以及许多其他返回ActiveRecord关系的方法。
Shirt.class
=> Class
Shirt.respond_to? :each
=> false
Shirt.respond_to? :reject
=> false
与内置查询方法类似,范围返回ActiveRecord关系。 ActiveRecord关系具有动态生成的类。它不是Enumerable
,而是响应Enumerable
方法:
red_shirts = Shirt.red
red_shirts.class
=> Shirt::ActiveRecord_Relation
red_shirts.respond_to? :each
=> true
red_shirts.respond_to? :reject
=> true
所以,你可以用这种方式编写你的方法:
def self.short_sleeved
all.reject { |object| object.short_sleeved == false }
end
然而,它会从数据库中加载所有Shirt
,然后在内存中过滤它们,这对于大量Shirt
的效率不如在数据库中进行过滤{ {1}}正如MZaragosa所说。你可以这样做
where
或
def self.short_sleeved
where short_sleeved: true
end