重写Rails的default_scope

如果我有一个默认范围的ActiveRecord :: Base模型:

class Foo < ActiveRecord::Base default_scope :conditions => ["bar = ?",bar] end 

有没有办法做一个Foo.find 而不使用default_scope条件? 换句话说,你可以重写一个默认的作用域?

我会认为在名称中使用“默认”会暗示它可覆盖的,否则将被称为像global_scope ,对吗?

简短的回答:除非你真的需要,否则不要使用default_scope 。 你可能会更好的命名范围。 这样说,你可以使用with_exclusive_scope覆盖默认的作用域,如果你需要。

看看这个问题的更多细节。

在Rails 3中:

 foos = Foo.unscoped.where(:baz => baz) 

如果您只需要更改default_scope定义的顺序,则可以使用reorder方法 。

 class Foo < ActiveRecord::Base default_scope order('created_at desc') end Foo.reorder('created_at asc') 

运行以下SQL:

 SELECT * FROM "foos" ORDER BY created_at asc 

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 

目前有可能unscope像:: :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having

但是如果可以的话,仍然请避免使用default_scope 。 这是为了你自己的好。

您可以使用with_exclusive_scope方法覆盖默认作用域。 所以:

 foos = Foo.with_exclusive_scope { :conditions => ["baz = ?", baz] } 
  • with_exclusive_scope文档

Rails 3的default_scope似乎不像Rails 2那样被覆盖。

例如

 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" 

在我的应用程序中,使用PostgreSQL,在默认范围内sortingWINS。 我删除了我所有的default_scopes,并在各处显式编码。

陷阱Rails3!

使用Rails 3+,您可以使用unscoped和merge的组合:

 # model User has a default scope query = User.where(email: "foo@example.com") # get rid of default scope and then merge the conditions query = query.unscoped.merge(query) 

那么,你可以随时使用旧时间最喜欢的find_by_sql和完整的查询。 例如:Model.find_by_sql(“SELECT * FROM models WHERE id = 123”)