views:

1569

answers:

2

I have a little example Rails app called tickets, which views and edits fictional tickets sold to various customers. In tickets_controller.rb, inside def index, I have this standard line, generated by scaffolding:

@tickets = Ticket.find(:all)

To sort the tickets by name, I have found two possible approaches. You can do it this way:

@tickets = Ticket.find(:all, :order => 'name')

... or this way:

@tickets = Ticket.find(:all).sort!{|t1,t2|t1.name <=> t2.name}

(Tip: Ruby documentation explains that sort! will modify the array that it is sorting, as opposed to sort alone, which returns the sorted array but leaves the original unchanged).

What strategy do you normally use? When might you use .sort! versus the :order => 'criteria' syntax?

Clarification

Originally, this question was going to be "why isn't the second approach working," but now it is working. Since I had documented two ways to do this, I thought I'd at least publish it for others to find. :)

+2  A: 

I specify an order in the ActiveRecord finder or in the model association because sorting using SQL is faster. You should take advantage of the features offered by the RDBMS when you're able to do so.

John Topley
+9  A: 

Use :order => 'criteria' for anything simple that can be done by the database (ie. basic alphabetical or chronological order). Chances are it's a lot faster than letting your Ruby code do it, assuming you have the right indexes in place.

The only time I could think you should use the sort method is if you have a complex attribute that's calculated at run-time and not stored in the database, like a 'trustworthiness value' based off number of good/bad responses or something. In that case it's better to use the sort method, but be aware that this will screw things up if you have pagination in place (each page will have ITS results in order, but the set of pages as a whole will be out of order).

Luke
Interesting. Why would it screw up the pagination if, as soon as I pull the info from the database, I sort! it? Wouldn't that happen before it's passed off for pagination/display?
Nathan Long
The find/paginate call will get the data in blocks of (lets say) 20. Those 20 will be picked out of the database according to whatever :order clause you had, THEN sorted by your custom sort function. This means that the page-set will be sorted by the :order clause, and each page by your function.
Luke
Thanks for the excellent explanations!
Nathan Long