2016-05-13 74 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

這徹底解答了我的問題。你提出這個效率很低是很有價值的,但是在我的情況下,我需要的最後一個範圍對於一個簡單的查詢來說是不可能的。到那時,我將有一個足夠小的清單,它「應該」永遠不會成爲問題。謝謝! –

相關問題