如何通过Ruby on Rails中的关联来订购has_many?
鉴于以下AR模型,我想在给予任务句柄时按姓氏的字母顺序对用户进行sorting:
#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
我想得到一个任务,然后导航到其分配的用户, 并按字母顺序sorting用户列表 。
我一直在想,我应该能够将:order
子句添加到has_many :users, :through => :assignments
像这样:
#task.rb has_many :assignments has_many :users, :through => :assignments, :order => 'last_name, first_name'
然而这是行不通的。
在给定任务时,如何按last_name
sorting用户?
由于条件参数在Rails 4中已被弃用,所以应该使用范围块:
has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments
Rails 3.x版本:
has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name'
更新:这只适用于Rails 3.x(也许在此之前)。 对于4+,请参阅其他答案。
MGPalmer's
方法运作良好,但涉及表名。 有一个更好的方法来做到这一点:
has_many :users, :through => :assignments, :order => [ :last_name, :first_name ]
这会为你工作吗?
# User.rb class User < ActiveRecord::Base default_scope :order => 'last_name ASC' ... end
您可以定义其他命名范围,以便sorting时需要不同。
http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping
这对我有用(Rails 4.2)
在直通地图上应用sorting不会被保留下来,也就是说这还不足以让stream派sorting:
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
为了完成任务,这应该是这样的(未经testing)
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
您也可以在赋值表上创build一个新的“sort_order”列,并添加一个默认的作用域
default_scope { order('sort_order desc')}
到你的作业模型。
我正在使用Rails(5.0.0.1),并可以在我的模型组中使用这个sintaxe进行sorting,通过group_users有许多用户:
# Associations. has_many :group_users has_many :users, -> { order(:name) }, through: :group_users
调整代码,以适应您的需要,将工作。