如何在Rails中自动sortinghas_many关系?

这似乎是一个非常简单的问题,但我没有看到它在任何地方的答案。

如果您有铁轨,

class Article < ActiveRecord::Base has_many :comments end class Comments < ActiveRecord::Base belongs_to :article end 

为什么你不能用这样的东西来sorting:

 @article.comments(:order=>"created_at DESC") 

命名作用域如果需要大量引用,甚至人们可以这样做:

 @article.comments.sort { |x,y| x.created_at <=> y.created_at } 

但有些事情告诉我应该更简单。 我错过了什么?

您可以使用has_many本身的选项来指定裸集合的sorting顺序:

 class Article < ActiveRecord::Base has_many :comments, :order => 'created_at DESC' end class Comment < ActiveRecord::Base belongs_to :article end 

或者,如果您想要一个简单的非数据库sorting方法,请使用sort_by :

 article.comments.sort_by &:created_at 

收集这与ActiveRecord添加方法的订购:

 article.comments.find(:all, :order => 'created_at DESC') article.comments.all(:order => 'created_at DESC') 

您的里程可能会有所不同:上述解决scheme的性能特点将会发生巨大变化,具体取决于您如何获取数据以及您使用哪个Ruby来运行您的应用程序。

至于Rails 4,你可以这样做:

 class Article < ActiveRecord::Base has_many :comments, -> { order(created_at: :desc) } end class Comment < ActiveRecord::Base belongs_to :article end 

对于has_many :through关系,参数顺序很重要(必须是第二个):

 class Article has_many :comments, -> { order('postables.sort' :desc) }, :through => :postable end 

如果你总是想要以相同的顺序访问评论,不pipe上下文你也可以通过default_scope内部Comment如下:

 class Comment < ActiveRecord::Base belongs_to :article default_scope { order(created_at: :desc) } end 

但是,这个问题可能会因为这个问题中讨论的原因而出现问题 。

在Rails 4之前,你可以指定order作为关系的关键,如:

 class Article < ActiveRecord::Base has_many :comments, :order => 'created_at DESC' end 

正如Jim提到的,在获取结果之后,也可以使用sort_by ,尽pipe在任何大小的结果集中,与通过SQL / ActiveRecord进行sorting相比,这将显着更慢(并且使用更多的内存)。

如果您正在做某些事情,在某些情况下,添加默认订单非常麻烦,或者您想在某些情况下覆盖默认设置,则在提取操作本身中指定它是很简单的:

 sorted = article.comments.order('created_at').all 

如果您使用的是Rails 2.3,并且希望对该对象的所有集合使用相同的默认sorting,则可以使用default_scope来sorting集合。

 class Student < ActiveRecord::Base belongs_to :class default_scope :order => 'name' end 

那么如果你打电话

 @students = @class.students 

它们将根据您的default_scope进行sorting。 TBH在一般意义上的顺序是默认范围的唯一很好的使用。

你可以使用ActiveRecord的find方法来获取你的对象并对它们进行sorting。

  @article.comments.find(:all, :order => "created_at DESC") 

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

如果你需要传递一些额外的参数,例如dependent: :destroy或者其他的参数,你应该在lambda之后加上这样的参数:

 class Article < ActiveRecord::Base has_many :comments, -> { order(created_at: :desc) }, dependent: :destroy end