Answers:
简短答案:default_scope
除非确实需要,否则请勿使用。使用命名范围可能会更好。话虽如此,您可以根据with_exclusive_scope
需要覆盖默认范围。
请查看此问题以获取更多详细信息。
default_scope
似乎是一个好主意,但可能会在应用程序的生命周期内引起多次头痛。
default_scope
是一种出色的工具,在某些情况下您可以选择其他方式,但这default_scope
只是正确的做法。例如,当您的Product
模型带有inactive
标志时,default_scope { where inactive: false }
最好设置a ,因为99%的情况下,您都不想显示无效的产品。然后,您只需调用unscoped
其余1%的案例,这可能是管理面板。
在Rails 3中:
foos = Foo.unscoped.where(:baz => baz)
def self.random; unscoped.order('rand()'); end
unscoped会删除其前面的所有sql,而不仅仅是default_scope下列出的内容。从技术上来说,这是正确的答案,但请小心使用unstopped
unscoped
当它可以直接遵循模型时,例如Foo.unscoped.blah()
可以,但从不Foo.blah().unscoped
。
如果只需要更改中定义的顺序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
scope :without_default_order, -> { reorder("") }
,您可以做类似的事情。Foo.without_default_order.order("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,默认作用域中的排序为WINS。我要删除所有default_scopes并将其明确地编码在任何地方。
陷阱Rails3!
Bar.foos.reorder(:created_at => :asc)
好吧,您始终可以将旧时的收藏夹find_by_sql
与完整的查询一起使用。例如:Model.find_by_sql(“ SELECT * FROM models WHERE id = 123”)