2011-06-21 82 views
3

我無法找出所有沒有酒吧的Foos的範圍方法。那是:Rails適用於0尺寸的關聯

class Foo < ActiveRecord::Base 

    has_may :bars 

end 

class Bar < ActiveRecord::Base 

    belongs_to :foo 

end 

我想寫一個範圍方法,返回我沒有酒吧的所有foos。就像這樣:

class Foo < ActiveRecord::Base 

    has_may :bars 

    scope :has_no_bars, includes(:bars).where("COUNT(foo.bars) = 0") 

end 

但我不明白適當的語法。任何幫助?如果更容易使用MetaWhere解決方案,很高興。

+0

你能否支付在Foo表中存儲酒吧的緩存數? (使用計數器緩存) – Dogbert

+1

嗯..可以工作,但我想知道實際查詢應該是什麼。 – MissingHandle

回答

3

您需要一個子選擇或一個外部連接+組+獨特的解決您的問題。 AFAIK對於Rails的AR來說是不可能的。

的近似值是使用AR的counter-cache功能,使您的查詢那樣簡單

scope :has_no_bars, where("bars_count = 0") 

這不是100%正確的關係,明智的,但爲您節省了大量的工作,還可以進行擴展好得多。

+0

好吧,所以在中間的時間,我發現這個職位:http://stackoverflow.com/questions/3676588/creating-a-named-scope-for-no-children-in-a-has-many-協會 它使用子選擇。你是說,性能明智,只是使用反高速緩存? – MissingHandle

+0

跟進 - 反高速緩存'一切'的缺點是什麼?或計數緩存算作最佳實踐? – MissingHandle

+0

從性能角度看,子選擇總是危險的(因爲數據庫無法優化查詢),而計數器高速緩存列是免費的(只有在創建關聯記錄時必須更新高速緩存)。但是計數器緩存可能不是100%正確的(如果你不是通過Rails更新記錄或者跳過了回調,可能會失去一些數字)。 –