How can I order has_many through union in Ruby on Rails?

Given the following AR models, I would like to sort users alphabetically by name when defining a task handle:

#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 the task, then go to the assigned users, and sort the list of users alphabetically.

I keep thinking that I should add the :order clause to has_many :users, :through => :assignments as follows:

 #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_name when given?

+55
ruby-on-rails has-many-through
Feb 05 '10 at 7:26
source share
8 answers

Since argument arguments are deprecated in Rails 4, scope blocks should be used:

 has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments 
+68
Oct 02 '13 at
source share

Rails version 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.

+37
Oct 18 '11 at 11:19
source share

MGPalmer's approach works well, however the table name is used. There is a better way to do this:

 has_many :users, :through => :assignments, :order => [ :last_name, :first_name ] 
+12
Sep 24 '12 at 5:17
source share

Will this work for you?

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

You can define other named areas because the sorting must be different.

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

+7
Feb 05 '10 at 7:45
source share

This works for me (Rails 4.2)

Application of the order on the pass-through map is not saved, since this is not enough to order the genres:

 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 rewrite this for each instance:

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

To do this job for assignments, it must 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 
+6
Jul 31 '15 at 15:55
source share

I use Rails (5.0.0.1) and can sort using this syntax in my Group model, in which there are many users through group_users:

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

Customize the code to suit your needs, which will work.

+4
Dec 27 '16 at 16:28
source share

You can also create a new sort_order column in the assignment table and add a default scope, e.g.

 default_scope { order('sort_order desc')} 

to your task.

+2
Jan 16 '13 at 6:27
source share

has_many: users, β†’ {order (: last_name ,: first_name)}, through =>: destination, source: 'user'

0
Apr 16 '19 at 16:59
source share



All Articles