You can do this:
Appointment.find(:all, :include => {:patient}, :order => 'people.last_name')
What you're doing is grabbing all the appointments, and their associated patients at the same time. You don't have to worry about patients vs doctors because all the people rows retrieved will be patient records.
In order to have a doctor-centric list, just change :patient to :doctor in the above example.
EDIT: I figured out the solution when you eager load both patients and doctors. It gets a little complex. First, I recreated a simple version of your 4 models in a blank rails app, then tried to run the find with :order => 'patients.name'
:
Appointment.find(:all, :include => [:patient, :doctor], :order => 'patients.name')
Of course if failed, but it also spit out the SQL query it attempted:
SELECT
"appointments"."id" AS t0_r0,
"appointments"."name" AS t0_r1,
"appointments"."doctor_id" AS t0_r2,
"appointments"."patient_id" AS t0_r3,
"appointments"."created_at" AS t0_r4,
"appointments"."updated_at" AS t0_r5,
"people"."id" AS t1_r0,
"people"."name" AS t1_r1,
"people"."type" AS t1_r2,
"people"."created_at" AS t1_r3,
"people"."updated_at" AS t1_r4,
"doctors_appointments"."id" AS t2_r0,
"doctors_appointments"."name" AS t2_r1,
"doctors_appointments"."type" AS t2_r2,
"doctors_appointments"."created_at" AS t2_r3,
"doctors_appointments"."updated_at" AS t2_r4
FROM "appointments"
LEFT OUTER JOIN "people" ON "people".id = "appointments".patient_id AND ("people"."type" = 'Patient' )
LEFT OUTER JOIN "people" doctors_appointments ON "doctors_appointments".id = "appointments".doctor_id AND ("doctors_appointments"."type" = 'Doctor' )
ORDER BY patients.name
Now we can see how rails forms a query like this. The first association to use a given table gets the table name directly - "people". Subsequent associations get a combo of the association and original table - "doctors_appointments".
It may seem a little messy, but this call gives you ordered by patients:
Appointment.find(:all, :include => [:patient, :doctor], :order => 'people.name')
And this one gives you ordered by doctors:
Appointment.find(:all, :include => [:patient, :doctor], :order => 'doctors_appointments.name')
Of course, in my example I just had a simple name field for each person, and you'll be using "last_name" instead. But you get the idea. Does this work for you?
ONE LAST EDIT:
I would put these in finders, so you don't need to mess with the table names anywhere else in your code. I'd do it like this:
class << self
def order_by_patient(field='last_name')
find(:all, :include => [:patient, :doctor], :order => "people.#{field}")
end
def order_by_doctor(field='last_name')
find(:all, :include => [:patient, :doctor], :order => "doctors_appointments.#{field}")
end
end
Now you can call them from anywhere, and even sort by the field you want.