0

ActiveRecordモデルで次のスコープを検討してください。

scope :onsale, where(:sales_state => "onsale")
scope :outdated, where(:sales_state => "outdated")
scope :onsale_or_outdated, where(" sales_state = 'onsale' OR sales_state = 'outdated' ")

Railsがでオーバーライド:onsaleすることを知っているのに:outdated、ではない:onsaleのは:onsale_or_outdatedなぜですか?

私のユースケース:

多くのスコープを持つリレーションオブジェクトがあり(保存された検索だとしましょう)、そのうちの1つはです:onsale。それから別の関係を作りたいのですが、今回はまたはのsales_stateどちらかonsaleになりたいですoutdated

を使用するrelation.onsale_or_outdatedと、sales_stateはオーバーライドされず、新しい条件が追加されるだけです。

[...] WHERE "cars"."sales_state" = 'onsale' [...] AND (("cars"."sales_state" = 'onsale' OR "cars"."sales_state" = 'outdated'))

このコンテキストで'または'-ed条件を使用するにはどうすればよいですか?

4

1 に答える 1

1

Relation.onsale_or_outdatedを使用すると、sales_stateはオーバーライドされず、新しい条件が追加されるだけです。

これがスコープの仕組みです。それらは、置き換えるのではなく、追加します。相互に排他的なスコープが2つある場合は、両方ではなく、どちらか一方を使用する必要があります。特殊なケースは、スコープに:symbol = <value>構文の単一フィールドが含まれる場合です。Railsは、一方のスコープがもう一方のスコープをキャンセルできるほどスマートです。あなたの場合、onsale_or_updatedスコープは単なる文字列であり、Railsにはどのフィールドが関係しているかを知る手段がないため、スコープはチェーンされています。

SQLのblobの代わりにフィールド/値を使用するようにスコープを書き直して、Railsがどのフィールドが関係しているかを認識できるようにする必要があります。

scope :onsale_or_outdated, where(:sales_state => %w(onsale outdated))

onsale_or_outdatedまたは、スコープのみを使用する場合はunscope、関係を作成してスコープを再適用できます。

relation.unscoped.onsale_or_outdated

これにより、以前に適用されたスコープがすべて削除されることに注意してください。

于 2012-10-18T16:07:12.877 に答える