rails模型的默认排序顺序?

时间:2010-08-03 05:01:05

标签: ruby-on-rails

我想在我的模型中指定默认排序顺序。

因此,当我执行.where()而未指定.order()时,它会使用默认排序。但是,如果我指定.order(),它将覆盖默认值。

3 个答案:

答案 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