Forum: Ruby on Rails Finding and Sorting

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
7bf14ecf85afe06dd73c5a04506c5155?d=identicon&s=25 mazurr@gmail.com (Guest)
on 2007-01-19 16:31
(Received via mailing list)
I am just trying to work through David Black's block of code from Ruby
For Rails, on page 80.

def all
  @order = params[:order] || "number"
  sort_proc = case @order
    when "author" then lambda {|r| [r.user.name.downcase, r.number] }
    when "status","title" then lambda {|r| [r.send(@order).downcase,
r.number]}
    when "number" then lambda {|r| -r.number }
  end
  @rcrs = Rcr.find(:all).sort_by &sort_proc
end


I can get this to work just fine.  But how about this...if the user
passes the "order" parameter as author, I want to sort nearly the same
way, but with r.user.name descending.  I know this errors, but I mean
something like:
    when "author" then lambda {|r| [r.user.name.downcase DESC,
r.number] }

How do you control the ascending/descending on one of the two sort
parameters?

Also, in the "number" sort option, what is the - doing in the part
-r.number?  I have experimented with it, but haven't determined what it
is doing.

Thanks,
Rob
3252509ae024ded864bd341e893fab2d?d=identicon&s=25 eth1 (Guest)
on 2007-09-25 22:40
(Received via mailing list)
I hadn't seen this code but it was a good exercise to figure out what
was going on.  Here's how it looks to me:

(1) as for the ascending, descending, probably it would be easiest to
simply throw a .reverse on the end of that string.  This code doesn't
seem to be aimed at efficiency so much as clarity (I'd rather use the
database to take care of ordering in the find), so I don't think the
extra method call is too heavy.

(2) the -r.number is a way of sorting descending ([1,2,3] becomes
[-3,-2,-1])

I was happy to learn the array trick with sort_by from this example
though.  Sort sorts arrays according to their content values, starting
from first to last (so [[1,2],[3,4],[3,2]].sort evals to
[[1,2],[3,2],[3,4]]. This example then uses arrays as the sort_by map
to sort by various criteria.

Still, I don't understand why one would go this way instead of letting
the database do the sorting.

Ethan
B0f09f622c913a13b9bfd332fca56563?d=identicon&s=25 Dan Manges (dcmanges)
on 2007-09-25 22:45
(Received via mailing list)
mazurr@gmail.com wrote:
> I can get this to work just fine.  But how about this...if the user
> passes the "order" parameter as author, I want to sort nearly the same
> way, but with r.user.name descending.  I know this errors, but I mean
> something like:
>     when "author" then lambda {|r| [r.user.name.downcase DESC,
> r.number] }
>
> How do you control the ascending/descending on one of the two sort
> parameters?

The easiest way to sort descending is to use the regular .sort method
and reverse the variables coming from the block:

["a","b","c"].sort { |x,y| y <=> x } #=> ["c","b","a"]

For sorting my case insensitive name in reverse, it would look like:

Author.find(:all).sort { |x,y| y.name.downcase <=> x.name.downcase }

If you do this a lot you could make a method for it (I don't think one
already exists):

class Array
  def sort_by_reverse(&block)
    sort { |x,y| block.call(y) <=> block.call(x) }
  end
end

Then: ["a","B","c","D"].sort_by_reverse { |s| s.downcase } #=>
["D","c","B","a"]

I'm not sure if this is the most efficient way, or if .sort.reverse if
more efficient, but it works.

Dan Manges
This topic is locked and can not be replied to.