Ruby-on-rails 覆盖 Rails default_scope
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1834159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding a Rails default_scope
提问by Gareth
If I have an ActiveRecord::Base model with a default-scope:
如果我有一个默认范围的 ActiveRecord::Base 模型:
class Foo < ActiveRecord::Base
default_scope :conditions => ["bar = ?",bar]
end
Is there any way to do a Foo.findwithoutusing the default_scopeconditions? In other words, can you override a default scope?
有没有办法在Foo.find不使用default_scope条件的情况下做 a ?换句话说,您可以覆盖默认范围吗?
I would have thought that using 'default' in the name would suggest that it wasoverridable, otherwise it would be called something like global_scope, right?
我会认为在名称中使用“默认”会表明它是可覆盖的,否则它会被称为类似的东西global_scope,对吧?
采纳答案by P?r Wieslander
Short answer: Do not use default_scopeunless you really have to. You'll probably be better off with named scopes. With that said, you can use with_exclusive_scopeto override the default scope if you need to.
简短回答:default_scope除非真的必须,否则不要使用。使用命名范围可能会更好。话虽如此,with_exclusive_scope如果需要,您可以使用覆盖默认范围。
Have a look at this questionfor more details.
看看这个问题了解更多细节。
回答by Vincent
In Rails 3:
在 Rails 3 中:
foos = Foo.unscoped.where(:baz => baz)
回答by GuiGS
If all you need is to change the order defined in default_scope, you can use the reordermethod.
如果您只需要更改 中定义的顺序default_scope,则可以使用reorder方法。
class Foo < ActiveRecord::Base
default_scope order('created_at desc')
end
Foo.reorder('created_at asc')
runs the following SQL:
运行以下 SQL:
SELECT * FROM "foos" ORDER BY created_at asc
回答by jibiel
Since 4.1you can use ActiveRecord::QueryMethods#unscopeto fight default scope:
由于4.1您可以使用ActiveRecord::QueryMethods#unscope来对抗默认范围:
class User < ActiveRecord::Base
default_scope { where tester: false }
scope :testers, -> { unscope(:where).where tester: true }
scope :with_testers, -> { unscope(:where).where tester: [true, false] }
# ...
end
It is currentlypossible to unscopestuff like: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having.
这是目前能够unscope喜欢的东西::where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having。
But still please avoid using of default_scopeif you can. It's for your own good.
但如果可以,请避免使用 ofdefault_scope。这是为了你好。
回答by John Topley
You can override a default scope using the with_exclusive_scopemethod. So:
您可以使用该with_exclusive_scope方法覆盖默认范围。所以:
foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] }
with_exclusive_scopedocumentation
回答by vanboom
Rails 3 default_scope does not appear to get overridden like it did in Rails 2.
Rails 3 default_scope 似乎没有像 Rails 2 那样被覆盖。
e.g.
例如
class Foo < ActiveRecord::Base
belongs_to :bar
default_scope :order=>"created_at desc"
end
class Bar < ActiveRecord::Base
has_many :foos
end
> Bar.foos
SELECT * from Foo where bar_id = 2 order by "created_at desc";
> Bar.unscoped.foos
SELECT * from Foo; (WRONG! removes the "has" relationship)
> Bar.foos( :order=>"created_at asc" ) # trying to override ordering
SELECT * from Foo where bar_id = 2 order by "created_at desc, created_at asc"
In my app, using PostgreSQL, the ordering in the default scope WINS. I'm removing all of my default_scopes and coding it in explicitly everywhere.
在我的应用程序中,使用 PostgreSQL,默认范围内的排序 WINS。我正在删除我所有的 default_scopes 并在任何地方明确地对其进行编码。
Pitfall Rails3!
陷阱 Rails3!
回答by santervo
With Rails 3+ you can use a combination of unscoped and merge:
使用 Rails 3+,您可以使用 unscoped 和 merge 的组合:
# model User has a default scope
query = User.where(email: "[email protected]")
# get rid of default scope and then merge the conditions
query = query.unscoped.merge(query)
回答by wbharding
On Rails 5.1+ (and maybe earlier, but I've tested it works on 5.1) it is possible to unscope a specific column, which imho is the ideal solution for removing a default_scopein a fashion that can be used inside a named scope. In the case of the OPs default_scope,
在 Rails 5.1+(也许更早,但我已经测试过它适用于 5.1)上,可以取消特定列的范围,恕我直言,这是以default_scope可在命名范围内使用的方式删除 a 的理想解决方案。在 OP 的情况下default_scope,
Foo.unscope(where: :bar)
Or
或者
scope :not_default, -> { unscope(where: :bar) }
Foo.not_default
Will both result in a sql query that doesn't apply the original scope, but does apply whatever other conditions get merged into the arel.
两者都会导致不应用原始范围的 sql 查询,但会应用合并到 arel 中的任何其他条件。
回答by Ady Rosen
Well, you can always use the old time favorite find_by_sqlwith the complete query.
For example:
Model.find_by_sql("SELECT * FROM models WHERE id=123")
好吧,您始终可以将旧时收藏夹find_by_sql与完整查询一起使用。例如: Model.find_by_sql("SELECT * FROM models WHERE id=123")

