如何通过 Ruby on Rails 中的关联订购 has_many?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2205618/
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 order a has_many through association in Ruby on Rails?
提问by rswolff
Given the following AR models, I would like to sort users alphabetically by last name when given a handle to a task:
鉴于以下 AR 模型,我想在获得任务句柄时按姓氏的字母顺序对用户进行排序:
#user
has_many :assignments
has_many :tasks, :through => :assignments
#assignment
belongs_to :task
belongs_to :user
#task
has_many :assignments
has_many :users, :through => :assignments
I would like to get a task then navigation to its assigned users, and sort the user list alphabetically.
我想获得一个任务,然后导航到其分配的用户,并按字母顺序对用户列表进行排序。
I keep thinking that I should be able to add the :orderclause to has_many :users, :through => :assignmentslike this:
我一直认为我应该能够像这样添加:order子句has_many :users, :through => :assignments:
#task.rb
has_many :assignments
has_many :users, :through => :assignments, :order => 'last_name, first_name'
however this does not work.
但是这不起作用。
How can I sort users by last_namewhen given a task?
如何根据last_name给定任务对用户进行排序?
回答by Daniel
Since condition arguments are deprecated in Rails 4, one should use scope blocks:
由于 Rails 4 中不推荐使用条件参数,因此应该使用作用域块:
has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments
回答by Martin T.
Rails 3.x version:
Rails 3.x 版本:
has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name'
UPDATE: This only works in Rails 3.x (maybe before that too). For 4+, see other answers.
更新:这只适用于 Rails 3.x(也许在那之前)。对于 4+,请参阅其他答案。
回答by denis.peplin
The M.G.Palmer'sapproach works well, however table name is involved. There is a better way to do it:
该M.G.Palmer's方法运行良好,但涉及表名。有一个更好的方法来做到这一点:
has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
回答by Antony Sastre
Would this work for you?
这对你有用吗?
# User.rb
class User < ActiveRecord::Base
default_scope :order => 'last_name ASC'
...
end
You can define other named scopes for when sorting needs to be different.
当排序需要不同时,您可以定义其他命名范围。
http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping
http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping
回答by edx
This works for me (Rails 4.2)
这对我有用(Rails 4.2)
Applying an ordering on the through map is not preserved, aka this is not enough to have the genres ordered:
不会保留在直通地图上应用排序,也就是这不足以对流派进行排序:
has_many :disk_genre_maps,
-> {order('disk_genre_map.sort_order')},
:inverse_of => :disk,
:dependent => :destroy,
:autosave => true
has_many :genres, # not sorted like disk_genre_maps
:through => :disk_genre_maps,
:source => :genre,
:autosave => true
So I overwrite this per instance:
所以我每个实例都覆盖这个:
def genres # redefine genres per instance so that the ordering is preserved
self.disk_genre_maps.map{|dgm|dgm.genre}
end
To make that work for assignments, this should be something like this (untested)
为了使这项工作适用于作业,这应该是这样的(未经测试)
def genres= some_genres
self.disk_genre_maps = some_genres.map.with_index do |genre, index|
DiskGenreMap.new(disk:self, genre:genre, sort_order:index)
end
end
回答by Ricardo Emerson
I am using Rails (5.0.0.1) and could make the sort with this syntax in my model Group that has many users through group_users:
我正在使用 Rails (5.0.0.1),并且可以在我的模型组中使用此语法进行排序,该组通过 group_users 拥有许多用户:
# Associations.
has_many :group_users
has_many :users, -> { order(:name) }, through: :group_users
Adjust the code to your need that will work.
根据您的需要调整代码,使其有效。
回答by Yogzzz
You could also create a new 'sort_order' column on the assignment table, and add a default scope like
您还可以在分配表上创建一个新的“sort_order”列,并添加一个默认范围,如
default_scope { order('sort_order desc')}
to your assignments model.
到你的任务模型。
回答by user223697
has_many :users, -> { order(:last_name, :first_name) }, :through => :assignments, source: 'user'
has_many :users, -> { order(:last_name, :first_name) }, :through => :assignments, source: 'user'

