In this example I’ll show you how easy it is to sort an array of (the same kind of) objects by an attribute. Let’s say you have an array of User objects that have the attributes ‘name’ and ‘login_count’. First, find all users.
@users = User.find(:all)
Now, we have to sort this array by ‘name’. Since we don’t know if any user used capitals in his name or not, we use ‘downcase’ to sort without case sensitivity.
A small not. ’sort’ returns a new array and leaves the original unchanged. You may want to just reorder the @users array, so use the ’sort!’ method. The ‘!’ indicates it’s a destructive method. It will overwrite the current @users array with the new sorting.
@users.sort! { |a,b| a.name.downcase < => b.name.downcase }
That’s all! Since strings are comparable, this will sort you user objects alphabetically by name. Want to sort on login_count instead?
@users.sort! { |a,b| a.login_count < => b.login_count }
So, now you can easily sort any object in an array just like you want it too!

User.find(:all).sort_by {|u| u.name.downcase} is ook mogelijk …..
@dovadi: Yes, that’s also possible, and probably the way you’ll use it in your controller. However, for this example, I’ve split off the User.find(:all) part to emphasize on the different sorting options you have.
what about sorting by more than one attribute?
yeah I’m very interested in the reply to that question as well.
For intstance, suppose you have an array of Dates you want to sort by year, then month, then day. with all three being separate attributes of the Date objects
If this is for Rails, and the find makes it look like it might be, then this is another option:
User.find(:all, :order => “name”)
Mysql sorting, at least, is case insensitive:
http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html
That gives you sorting by more than one attribute too (:order => “name, age DESC, height”).
Sorting by more than one attribute in straight Ruby would take some more thinking :)
@James: you are correct. In this example you could use the database to do the sorting for you, which has way better performance than rails.
The example, however, shows how to do it in Rails, in case you want to sort attributes that have a calculated value, for example.
There seem to be issues with using the database to do the sorting, as suggested by Ariejen I am doing a find_by_sql with an ‘order by’ in it and the array returned is not in the same order as requested by ‘order by’. This is a JRuby app, so there may be other issues. Sort by two fields fixes it. The second field can be nil (a database test for null didn’t help), so there is an extra test. The point is the code in the block can be as simple or as complex as you like, which is what people seemed to be interested in.
subject_groups.sort! do |a,b|
a.team == nil ? akey = a.name.downcase : akey = (a.name + a.team).downcase
b.team == nil ? bkey = b.name.downcase : bkey = (b.name + b.team).downcase
akey bkey
end
In the previous post the code got a little mangled: try again with simplification
teams_members.sort! do |a,b|
a.team == nil ? akey = a.name : akey = a.name + a.team
b.team == nil ? bkey = b.name : bkey = b.name + b.team
akey bkey
end
Regarding Adam’s question on sorting by more than one attribute, a sort block that returns:
[a.attrib_a, a.attrib_b] [b.attrib_a, b.attrib_b]for a and b should sort an array of objects first by attrib_a, and then by attrib_b. For more elaborate sorting, I sometimes have to put in expressions in the arrays.
Array (): http://www.ruby-doc.org/core/classes/Array.html#M000316
(Oops. Character codes.)
Regarding Adam’s question on sorting by more than one attribute, a sort block that returns:
[a.attrib_a, a.attrib_b] <=> [b.attrib_a, b.attrib_b]for a and b should sort an array of objects first by attrib_a, and then by attrib_b. For more elaborate sorting, I sometimes have to put in expressions in the arrays.
Array <=>(): http://www.ruby-doc.org/core/classes/Array.html#M000316
excelente, me sirvio mucho!!!!!!!!!!
Hi,
what if I have an array of dates in this format?
["", "2008/7/27", "2008/10/27", "2008/10/24"]
or this
["", "2008 7 27", "2008 10 27", "2008 10 24"]
thanks
Im trying to sort with two atributtes but the first one is “name” and comes from model “Place” and the second comes from the relation of the Place with another model called “Rattings”. The “Rattings” gives to “Place” an atributte “rating” when i use “place.rating”
How can i sort the Places first by rating and that result I sort by name without mess the rating order ? Its a stable sorting proccess and i dont know how to do.
If someone want to know, i solved my stuff. Just did a sort_by{|x|[A,B...]}
Where A,B and so on can be any attribute, even if a result of a relation just like i wish: sort_by {|x|[x.rating,x.name,-x.people.size]}
And you can use minus signal before any therm to mean DESC order cuz the default is ASC order.
Hi there,
I tried:
@posts = Post.find(:all, :order => “priority”)
and keep getting a:
NameError in PostsController#edit
undefined local variable or method `“priority”’ for #
What is wrong here?
I’m an absolute beginner, so don’t blame me for obviuos mistakes :-/
Cheers and Thanks for the example!!
Nils
@Nils: You probably don’t have a ‘priority’ attribute on your Post model.
Can you do this without errors:
What is the return value of the last statement?
Hi Ariejan,
thanx for your in time response!
Your code fails, what works is:
post = Post.find(params[:id])
post.priority
Cheers,
Nils
@Nils
That’s quite strange because
is valid ActiveRecord usage.
What version of Rails are you using?
You’re right, I left :all in instead of :first. So your first statement works, which means (at least from my understanding, that there is a priority field which I should be able to sort with. Right?
You can also use the symbol to Proc shorthand in Rails if you are just sorting on an attribute:
User.find(:all).sort_by(&:name)
But its definitely better to do the sorting in the database if you can.
just a quick typo check..
this line:
@users.sort! { |a,b| a.name.downcase b.name.downcase }
should be:
@users.sort! { |a,b| a.name.downcase b.name.downcase }
note the spacing..
thanks for the tip! works like a charm..
just a quick note..
you find yourself in this position ALOT..
like:
@members = Group.find(id).members
Hey Eduardo,
Thanks for your Ruby tip on sorting by multiple attributes. Worked like a charm.
sort_by {|x|[x.rating,x.name,-x.people.size]}
Jim
Thanks this is the answer for what I needed
Thanks to the author and the commenters! Lots of help.
Thank you! just what I need to read right now…
Thanks for showing how to sort on multiple attributes – just what I needed!
A tip to others, you can reverse sort just by changing the positions of a and b.
i.e. like this:
@users.sort! { |a,b| b.name.downcase a.name.downcase }
(oops, the comment system modified my code above – there should be a LESS THAN EQUALS GREATER THAN after the first downcase above)