views:

26

answers:

3

Previously I ordered my posts as this :

@posts = Post.find(:all, :order => "created_at DESC")

But now I want to replace created_at with a custom method I wrote in the Post model that gives a number as its result.

My guess:

@posts = Post.find(:all, :order => "custom_method DESC")

which fails..

+1  A: 

Well, just Post.find(:all) would return an array of AR objects. So you could use Array.sort_by and pass it a block, and since those records are already fetched, you can access the virtual attribute inside the block that sort_by takes.

RDoc: Enumerable.sort_by

Robbie
+2  A: 

It fails because you are asking your db to do the sorting.

@posts = Post.all.sort {|a,b| a.custom_method <=> b.custom_method}

Note that this becomes non-trivial when you want to start paging results and no longer wish to fetch .all. Think about your design a bit before you go with this.

jdl
NZKoz
A: 

Just to expand on @Robbie's answer

Post.all.sort_by {|post| post.custom_method }.reverse
jwarchol
Be careful if there are going to be many posts. Getting them all out of the DB and loaded up into ActiveRecord objects is not free. When the number of records becomes large, the slow down will matter for a production application. A field that's actually in your database, with a proper index, and limiting the query to a paginated set is the way to go.
jwarchol
Pagination, yes granted. But proper index is negligible because my custom method produces a ranking based on time. Which is always changing. Thus the results can change instantaneously.
Trip
I've worked a little with ranking systems. They can be tricky to do in real time for large sets of records when the calculation is not trivial. Best of luck, if you find any useful techniques, please share :-)
jwarchol