2016-05-13 45 views
2

根据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

我不知道你正在尝试做? 'class Shirt {where(short_sleeve:true)} end'''将会做到 – MZaragoza

+1

根据APIDock,我的语法是假设工作...但是我发现一个线程在轨道git存储库已给出相同的错误。解决的办法是把所有的东西都放在枚举器上... all.reject {} https://github.com/rails/rails/issues/21943 –

回答

1

不能定义short_sleeved方法你试过因为ActiveRecord的类不是ActiveRecord的关系的方式。

您在Shirt上定义了short_sleevedShirt是一个ActiveRecord模型类。它本身不是一个ActiveRecord关系。它的方法包括allwhere以及许多其他返回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而言,这并不像在MZaragosa所建议的那样在数据库中使用where进行过滤。你可以做,像这样

def self.short_sleeved 
    where short_sleeved: true 
end 

scope :short_sleeved, -> { where short_sleeved: true } 
+1

我正在编写这个详细的答案,点评。如果它对别人有帮助,我会放弃它。 –

+0

这彻底解答了我的问题。你提出这个效率很低是很有价值的,但是在我的情况下,我需要的最后一个范围对于一个简单的查询来说是不可能的。到那时,我将有一个足够小的清单,它“应该”永远不会成为问题。谢谢! –

相关问题