2014-02-13 35 views
1

我想消除我寫的rails範圍內的實例方法,所以我可以有更好的可鏈接範圍。Rails 4範圍通過相關對象的狀態?

我有一個模型Offeringhas_many :assetsAssets有一列status。我創建了一個Offering範圍,看起來像這樣:

scope :available, -> { where(approved_for_sale: true).reject{|offering| !offering.assets_ready} } 

其中assets_readyOffering方法:

def assets_ready 
    assets.inject(1) {|memo, asset| memo && asset.ready_status_symbol == :ready} 
end 

因爲拒絕返回一個數組,我想找到一種方法,編寫不需要實例方法的作用域。

回答

2

試試這個:

scope :available, -> { 
         where(approved_for_sale: true) 
         .where("NOT EXISTS (SELECT 1 from assets a WHERE 
         a.offering_id = offerings.id AND a.ready_status <> 'ready')") 
        } 

解決方案由蒂姆的回答啓發,一個SQL的問題在這裏:Select parent if all children meet criteria

市場的回答會爲一些使用情況下工作,但該集團條款出臺一些奇怪的行爲與鏈接和計數;例如如果可用範圍使用.group

+0

不錯的解決方案@igmcdowell。我看到伯爵的奇怪迴應,你能提供一個鏈接問題的例子嗎? – markets

0

要實現可鏈式範圍,您必須使用ActiveRecord query api中的方法。

假設status列類型爲字符串,我想你需要的東西,如:

scope :available, -> { 
    where("offerings.approved_for_sale = ?", true). 
    joins("INNER JOIN assets AS all_as ON all_as.offering_id = offerings.id 
     LEFT JOIN assets AS ready_as ON ready_as.id = all_as.id AND ready_as.status = 'ready'"). 
    group("all_as.offering_id"). 
    having("COUNT(all_as.id) = COUNT(ready_as.id)") 
} 

它返回一個ActiveRecord::Relation,而不是一個Array

+0

如果資產的_any_具有status :: ready,而不是_all_,那麼這似乎會返回一個產品。否則,一個好的開始。 – Heliostatic

+0

對。關於Rails方面沒關係,但不正確的SQL查詢。我會編輯答案。 – markets