Sorting by computed temporary field


#1

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. :slight_smile:

Many thanks,
Chris


#2

Chris S. 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. :slight_smile:

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


#3

Hello Chris !

2006/3/21, Chris S. removed_email_address@domain.invalid:

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 !