2011-06-21 17 views
3

バーを持たないすべてのFoosのスコープ方法を理解するのに問題があります。つまり:Rails 0の関連付けのスコープ

class Foo < ActiveRecord::Base 

    has_may :bars 

end 

class Bar < ActiveRecord::Base 

    belongs_to :foo 

end 

私はバーを持たないすべてのフォースを返すスコープメソッドを記述したいと思います。何かが好き:

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- subselectを使用する関連 そして、カウンタキャッシュを使用するだけでパフォーマンスが賢明だと言っていますか? – MissingHandle

+0

フォローアップ - 「すべて」をカウンターキャッシュすることの欠点は何ですか?ベストプラクティスとしてカウンターキャッシュをカウントしていますか? – MissingHandle

+0

パフォーマンスの観点からは、カウンタキャッシュ列がフリーになっている間(DBがクエリを最適化できないため)、サブセレクトは常に危険です(関連付けられたレコードの作成時にキャッシュのみを更新する必要があります)。しかし、カウンタキャッシュは100%正確ではないかもしれません(Railsを使わずにレコードを更新した場合や、コールバックをスキップした場合には、いくつかの数値がずれている可能性があります)。 –

関連する問題