Forum: Ruby on Rails Sorting by computed temporary field

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.
75ceef25624b3e44943a3b7319ba9612?d=identicon&s=25 Chris Schumann (torgo)
on 2006-03-21 17:47
(Received via mailing list)
Hey all,

I'm rather new to Ruby and Rails (and not great with SQL), but I'm
developing a ride sharing app and would like to be able to sort on
something I don't have stored.

I have users, events, and rides, each of which has a zip code. Events
have_many rides, and rides belong_to events.

When an event is selected, I'd like to be able to show a list of rides
to that event, sorted by distance from the logged-in user.

What are some ways to do that? Here's what I can think of:

- Make a new find_and_sort method that adds a new @distance member
element and sorts the new collection. Would something like this work?

def find_and_sort(event_id)
   @rides = Ride.find(:all, :conditions => {"event_id = ?", event_id})"
   for ride in @rides
     ride.newdistance = distance_between_zips(session[:user].zip_code,
       Event.find(event_id).zip_code);
   end
   uhm.... sort @rides by newdistance
end

What if I want to also remove items from @rides before they are
displayed if that newdistance is too large or some other condition?

uhm... I'm stumped, I guess. That's why I'm here. :)

Many thanks,
Chris
75ceef25624b3e44943a3b7319ba9612?d=identicon&s=25 Chris Schumann (torgo)
on 2006-03-21 22:04
(Received via mailing list)
Chris Schumann wrote:
> to that event, sorted by distance from the logged-in user.
>       Event.find(event_id).zip_code);
>   end
>   uhm.... sort @rides by newdistance
> end
>
> What if I want to also remove items from @rides before they are
> displayed if that newdistance is too large or some other condition?
>
> uhm... I'm stumped, I guess. That's why I'm here. :)

OK. Can't do that.

But I should be able to overload <=>
So in my ride model, could I do this?

def self.<=>(other)
   distance_between_zips(session[:user].zip_code, self.zip_code)
     <=> distance_between_zips(session[:user].zip_code, other.zip_code)
end

Except... wow. Calling sort on the list means like n*log(n) comparisons,
and each compare calls the distance function twice, and each of those
has five trig functions... so a list of 100 rides would take 2000 trig
calls. Easy peasy!

Oh... do ActiveRecord objects mixin Comparable?

Comments please!

Chris S
3dd4b52a0946bd698b1d1635a46ea3a3?d=identicon&s=25 François Beausoleil (fbeausoleil)
on 2006-03-21 22:23
(Received via mailing list)
Hello Chris !

2006/3/21, Chris Schumann <chris@idlelion.net>:
> > def find_and_sort(event_id)
> >   @rides = Ride.find(:all, :conditions => {"event_id = ?", event_id})"
> >   for ride in @rides
> >     ride.newdistance = distance_between_zips(session[:user].zip_code,
> >       Event.find(event_id).zip_code);
> >   end
> >   uhm.... sort @rides by newdistance
> > end

@rides is an Array, and Array mixes in Enumerable.  See #sort_by:
http://www.ruby-doc.org/core/classes/Enumerable.html#M002092

Hope that helps !
This topic is locked and can not be replied to.