62

鉴于以下 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

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

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

#task.rb
has_many :assignments
has_many :users, :through => :assignments, :order => 'last_name, first_name'

但是这不起作用。

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

4

8 回答 8

71

由于 Rails 4 不推荐使用条件参数,因此应该使用范围块:

has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments
于 2013-10-02T13:56:37.903 回答
37

Rails 3.x 版本:

has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name'

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

于 2011-10-18T11:19:57.753 回答
12

M.G.Palmer's方法效果很好,但是涉及到表名。有一个更好的方法来做到这一点:

has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
于 2012-09-24T05:17:52.810 回答
7

这对我有用(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

所以我每个实例都覆盖这个:

def genres  # redefine genres per instance so that the ordering is preserved
    self.disk_genre_maps.map{|dgm|dgm.genre}
end

为了使这项工作适用于作业,这应该是这样的(未经测试)

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
于 2015-07-31T15:55:45.700 回答
7

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

# Associations.
has_many :group_users
has_many :users, -> { order(:name) }, through: :group_users

根据您的需要调整代码,这将起作用。

于 2016-12-27T16:28:08.790 回答
6

这对你有用吗?

# User.rb

class User < ActiveRecord::Base
 default_scope :order => 'last_name ASC'
 ...
end

当排序需要不同时,您可以定义其他命名范围。

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

于 2010-02-05T07:45:42.310 回答
2

您还可以在分配表上创建一个新的“sort_order”列,并添加一个默认范围,例如

default_scope { order('sort_order desc')}

到您的作业模型。

于 2013-01-16T06:27:46.317 回答
1

has_many :users, -> { order(:last_name, :first_name) }, :through => :assignments, source: 'user'

于 2019-04-16T16:59:05.463 回答