如何在Ruby on Rails中通过关联订购has_many?

rsw*_*lff 58 ruby-on-rails has-many-through

鉴于以下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
Run Code Online (Sandbox Code Playgroud)

我想获得一个任务然后导航到其分配的用户,并按字母顺序对用户列表进行排序.

我一直在想我应该能够添加这样的:order子句has_many :users, :through => :assignments:

#task.rb
has_many :assignments
has_many :users, :through => :assignments, :order => 'last_name, first_name'
Run Code Online (Sandbox Code Playgroud)

但这不起作用.

如何last_name在给定任务时对用户进行排序?

Dan*_*iel 69

由于条件参数在Rails 4中已弃用,因此应使用范围块:

has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments
Run Code Online (Sandbox Code Playgroud)


Mar*_* T. 37

Rails 3.x版本:

has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name'
Run Code Online (Sandbox Code Playgroud)

更新:这仅适用于Rails 3.x(也许在此之前).对于4+,请参阅其他答案.

  • 不工作,它说:订单不是关键.以下是Denial IS的答案. (2认同)

den*_*lin 12

M.G.Palmer's方法运行良好,但涉及表名.有一种更好的方法:

has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
Run Code Online (Sandbox Code Playgroud)


Ant*_*tre 7

这对你有用吗?

# User.rb

class User < ActiveRecord::Base
 default_scope :order => 'last_name ASC'
 ...
end
Run Code Online (Sandbox Code Playgroud)

您可以在排序需要不同时定义其他命名范围.

http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping

  • 很抱歉碰到一个老问题,但这可能与未来的读者有关:有些插件(例如acts_as_list)无法正常使用default_scope. (2认同)

edx*_*edx 6

这对我有用(Rails 4.2)

不保留在直通地图上应用排序,也就是说这不足以使类型排序:

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
Run Code Online (Sandbox Code Playgroud)

所以我在每个实例中覆盖这个:

def genres  # redefine genres per instance so that the ordering is preserved
    self.disk_genre_maps.map{|dgm|dgm.genre}
end
Run Code Online (Sandbox Code Playgroud)

为分配工作,这应该是这样的(未经测试)

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
Run Code Online (Sandbox Code Playgroud)


Ric*_*son 6

我正在使用 Rails (5.0.0.1),并且可以在我的模型组中使用此语法进行排序,该组通过 group_users 拥有许多用户:

# Associations.
has_many :group_users
has_many :users, -> { order(:name) }, through: :group_users
Run Code Online (Sandbox Code Playgroud)

根据您的需要调整代码,使其有效。