在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
我的用例:
我有一个有很多范围的关系对象(假设它是一个已保存的搜索),其中一个是: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'))
如何在此背景下使用我的'或'条件?
答案 0 :(得分:1)
如果我使用relation.onsale_or_outdated,则不会覆盖sales_state,只会添加新条件。
这就是范围的工作原理。他们追加,而不是取代。如果您有两个互斥的范围,则需要使用其中一个,而不是两个。特殊情况是当您的范围涉及:symbol = <value>
语法中的单个字段时。 Rails非常聪明,允许一个范围取消另一个范围。在您的情况下,onsale_or_updated
范围只是一个字符串,Rails无法判断涉及哪些字段,因此范围是链接的。
您应该重写范围以使用字段/值而不是一串SQL,因此Rails知道涉及哪些字段。
scope :onsale_or_outdated, where(:sales_state => %w(onsale outdated))
或者,如果您只想使用onsale_or_outdated
范围,则可以unscope
关系并重新应用范围:
relation.unscoped.onsale_or_outdated
请注意,这将删除以前应用的任何范围。