我想在我的模型中指定默认排序顺序。
因此,当我执行.where()
而未指定.order()
时,它会使用默认排序。但是,如果我指定.order()
,它将覆盖默认值。
答案 0 :(得分:506)
default_scope
这适用于Rails 4 +:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
对于Rails 2.3,3,你需要这样做:
default_scope order('created_at DESC')
对于Rails 2.x:
default_scope :order => 'created_at DESC'
如果created_at
是您想要进行默认排序的字段。
注意: ASC 是用于升序的代码, DESC 用于降序({{1 },不 desc
!)。
dsc
一旦你习惯了,你也可以使用scope
:
scope
对于Rails 2,您需要class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
。
named_scope
范围为您提供:published
而非。{1}}
Book.published
。
从Rails 3开始,您可以通过将这些方法与它们之间的句点连接在一起来“链接”这些方法,因此使用上述范围,您现在可以使用Book.find(:published => true)
。
使用此方法,在需要实际结果(延迟评估)之前,实际上不会执行查询,因此可以将7个范围链接在一起,但仅产生1个实际数据库查询,以避免执行7个单独查询时出现性能问题。 / p>
您可以使用传入的参数,例如日期或user_id(在运行时会发生变化,因此需要'懒惰评估',使用lambda,如下所示:
Book.published.confirmed
最后,您可以使用以下命令禁用默认范围:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
甚至更好:
Book.with_exclusive_scope { find(:all) }
将禁用任何过滤器(条件)或排序(排序依据)。
请注意,第一个版本适用于Rails2 +,而第二个版本(unscoped)仅适用于Rails3 +
<强>因此强>
......如果你在想,嗯,所以这些就像方法那样......,是的,这正是这些范围的确切之处!
它们就像拥有Book.unscoped.all
一样,但与红宝石一样,它们都是很好的小语法快捷方式(或“糖”),让你的事情更轻松!
事实上,它们是类级方法,因为它们在1组“所有”记录上运行。
然而,他们的格式正在改变,使用rails 4在使用#scope而不传递可调用对象时会出现弃用警告。例如范围:红色,其中(颜色:'red')应该更改到def self.method_name ...code... end
。
作为旁注,如果使用不当,默认 _scope可能会被滥用/滥用。
这主要是关于它被用于scope :red, -> { where(color: 'red') }
限制(过滤)默认选择(默认情况下错误主意)等操作的时候,而不仅仅是用于订购结果。
对于where
选择,只需使用常规命名范围。并在查询中添加该范围,例如where
其中Book.all.published
是命名范围。
总之,范围非常好,可以帮助您将模型推向“胖模型瘦控制器”DRYer方法。
答案 1 :(得分:107)
快速更新迈克尔上面的优秀答案。
对于Rails 4.0+,您需要将排序放在这样的块中:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
请注意,order语句放在由大括号表示的块中。
他们改变了它,因为它太容易传递动态的东西(比如当前时间)。这样可以解决问题,因为在运行时会计算块。如果您不使用块,则会收到此错误:
删除了不带块调用#default_scope的支持。例如,请使用
default_scope where(color: 'red')
代替default_scope { where(color: 'red') }
。 (或者你可以重新定义self.default_scope。)
正如@Dan在下面的评论中提到的那样,你可以做一个更加红宝石的语法:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
或多列:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
谢谢@Dan!
答案 2 :(得分:6)
您可以使用default_scope实现默认排序顺序 http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html