Ruby-on-rails 如何在 Rails 中自动对 has_many 关系进行排序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/738971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I automatically sort a has_many relationship in Rails?
提问by Brian Armstrong
This seems like a really simple question but I haven't seen it answered anywhere.
这似乎是一个非常简单的问题,但我还没有在任何地方看到它的回答。
In rails if you have:
在 Rails 中,如果您有:
class Article < ActiveRecord::Base
has_many :comments
end
class Comments < ActiveRecord::Base
belongs_to :article
end
Why can't you order the comments with something like this:
为什么你不能用这样的东西对评论进行排序:
@article.comments(:order=>"created_at DESC")
Named scope works if you need to reference it a lot and even people do stuff like this:
如果您需要大量引用命名范围,甚至人们也会这样做:
@article.comments.sort { |x,y| x.created_at <=> y.created_at }
But something tells me it should be simpler. What am I missing?
但有些东西告诉我它应该更简单。我错过了什么?
回答by Jim Puls
You can specify the sort order for the bare collection with an option on has_manyitself:
您可以使用一个选项指定裸集合的排序顺序has_many:
class Article < ActiveRecord::Base
has_many :comments, :order => 'created_at DESC'
end
class Comment < ActiveRecord::Base
belongs_to :article
end
Or, if you want a simple, non-database method of sorting, use sort_by:
或者,如果您想要一种简单的、非数据库的排序方法,请使用sort_by:
article.comments.sort_by &:created_at
Collecting this with the ActiveRecord-added methods of ordering:
使用 ActiveRecord 添加的排序方法收集它:
article.comments.find(:all, :order => 'created_at DESC')
article.comments.all(:order => 'created_at DESC')
Your mileage may vary: the performance characteristics of the above solutions will change wildly depending on how you're fetching data in the first place and which Ruby you're using to run your app.
您的进展可能会有所不同:上述解决方案的性能特征将发生巨大变化,具体取决于您首先如何获取数据以及您使用哪种 Ruby 来运行您的应用程序。
回答by Matt Sanders
As of Rails 4, you would do:
从 Rails 4 开始,你会这样做:
class Article < ActiveRecord::Base
has_many :comments, -> { order(created_at: :desc) }
end
class Comment < ActiveRecord::Base
belongs_to :article
end
For a has_many :throughrelationship the argument order matters (it has to be second):
对于has_many :through关系,参数顺序很重要(它必须是第二个):
class Article
has_many :comments, -> { order('postables.sort' :desc) },
:through => :postable
end
If you will always want to access comments in the same order no matter the context you could also do this via default_scopewithin Commentlike:
如果你总是希望访问注释以相同的顺序不管上下文中,您还可以通过做这个default_scope范围内Comment,如:
class Comment < ActiveRecord::Base
belongs_to :article
default_scope { order(created_at: :desc) }
end
However this can be problematic for the reasons discussed in this question.
Before Rails 4 you could specify orderas a key on the relationship, like:
在 Rails 4 之前,您可以指定order关系的键,例如:
class Article < ActiveRecord::Base
has_many :comments, :order => 'created_at DESC'
end
As Jim mentioned you can also use sort_byafter you have fetched results although in any result sets of size this will be significantly slower (and use a lot more memory) than doing your ordering through SQL/ActiveRecord.
正如吉姆提到的,您也可以sort_by在获取结果后使用,尽管在任何大小的结果集中,这将比通过 SQL/ActiveRecord 进行排序要慢得多(并且使用更多的内存)。
If you are doing something where adding a default order is cumbersome for some reason or you want to override your default in certain cases, it is trivial to specify it in the fetching action itself:
如果您正在做的事情由于某种原因添加默认订单很麻烦,或者您想在某些情况下覆盖默认订单,那么在获取操作本身中指定它是微不足道的:
sorted = article.comments.order('created_at').all
回答by nitecoder
If you are using Rails 2.3 and want to use the same default ordering for all collections of this object you can use default_scope to order your collection.
如果您使用的是 Rails 2.3 并希望对这个对象的所有集合使用相同的默认排序,您可以使用 default_scope 来排序您的集合。
class Student < ActiveRecord::Base
belongs_to :class
default_scope :order => 'name'
end
Then if you call
那么如果你打电话
@students = @class.students
They will be ordered as per your default_scope. TBH in a very general sense ordering is the only really good use of default scopes.
它们将根据您的 default_scope 进行排序。TBH 在非常一般的意义上排序是默认范围的唯一真正好的用途。
回答by vrish88
You can use ActiveRecord's find method to get your objects and sort them too.
您可以使用 ActiveRecord 的 find 方法来获取对象并对它们进行排序。
@article.comments.find(:all, :order => "created_at DESC")
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
回答by Max L.
And if you need to pass some additional arguments like dependent: :destroyor whatever, you should append the ones after a lambda, like this:
如果你需要传递一些额外的参数,比如dependent: :destroy或其他什么,你应该在 lambda 之后附加这些参数,如下所示:
class Article < ActiveRecord::Base
has_many :comments, -> { order(created_at: :desc) }, dependent: :destroy
end

