Как я могу упорядочить по атрибутам нескольких подклассов, которые наследуются от одного базового класса в Ruby on Rails? - PullRequest
2 голосов
/ 19 января 2010

У меня есть 4 класса - пациент, доктор, человек и назначение.Пациент и доктор являются подклассами человека.Назначение принадлежит пациенту и принадлежит доктору.

Я хочу написать оператор AR, чтобы отсортировать встречи по фамилии пациента, а другой - по фамилии врача, поскольку все встречи будут в сортируемой таблице.Я немного сбит с толку относительно того, что поместить в опцию «порядок» оператора AR find.Если я поставлю

:order => 'patient.last_name'

, я получу сообщение об ошибке mysql - «Неизвестный столбец« PatientLast_name », что имеет смысл, поскольку столбца пациента нет, это« Patient_id », ссылающийся на чужой объект« персона ».Конечно, я могу сортировать по person.last_name, но я не знаю, как указать, какого типа человека сортировать - доктора или пациента.

Я также должен отметить, что я использую опцию include для загрузки пациентаи врач.

ОБНОВЛЕНИЕ

Существует только таблица персоны и таблица встреч. Пациент и врач наследуют от персоны. Patient.last_name не будет работать, потому что тамнет таблицы пациентов.

Оператор AR:

find  :all,
                :include => [:doctor, :patient], 
                :order => 'something needs to go here'   

«Что-то должно идти сюда» должно быть оператором для заказа по фамилии врача или по фамилии пациента.

Ответы [ 2 ]

1 голос
/ 19 января 2010

Вы можете сделать это:

Appointment.find(:all, :include => {:patient}, :order => 'people.last_name')

То, что вы делаете - это захватывает все встречи и связанных с ними пациентов одновременно. Вам не нужно беспокоиться о пациентах против врачей, потому что все извлеченные строки людей будут записями пациентов.

Чтобы получить список, ориентированный на доктора, просто измените: пациента на: доктора в приведенном выше примере.

РЕДАКТИРОВАТЬ: Я нашел решение, когда вы хотите загрузить как пациентов, так и врачей. Это становится немного сложным. Сначала я воссоздал простую версию ваших 4 моделей в пустом приложении rails, а затем попытался запустить поиск с помощью :order => 'patients.name':

Appointment.find(:all, :include => [:patient, :doctor], :order => 'patients.name')

Конечно, если произошел сбой, но он также выполнил запрос SQL:

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

Теперь мы можем видеть, как rails формирует запрос, подобный этому. Первая ассоциация, которая использует данную таблицу, получает имя таблицы напрямую - "people". Последующие ассоциации получают комбинацию ассоциации и оригинальную таблицу - "doctor_appointments".

Это может показаться немного беспорядочным, но этот звонок дает вам распоряжение пациентов:

Appointment.find(:all, :include => [:patient, :doctor], :order => 'people.name')

А этот дает вам по приказу врачей:

Appointment.find(:all, :include => [:patient, :doctor], :order => 'doctors_appointments.name')

Конечно, в моем примере у меня просто было простое поле имени для каждого человека, и вы будете использовать вместо него «last_name». Но ты получил идею. Это работает для вас?

ОДИН ПОСЛЕДНИЙ РЕДАКТИРОВАТЬ:

Я бы поместил их в средства поиска, чтобы вам не приходилось связываться с именами таблиц где-либо еще в вашем коде. Я бы сделал это так:

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

Теперь вы можете вызывать их из любого места и даже сортировать по полю, которое хотите.

0 голосов
/ 20 января 2010

Я думаю, что вам, возможно, придется использовать ручное объединение, а не включение.

См. Руководство по запросам активных записей при объединении таблиц .

Затем можно создатьпсевдоним для имен таблиц и порядок их соответственно.

find.all(:joins => 'LEFT OUTER JOIN people dr ON dr.id = appointments.id'
  :order => dr.last_name
)

Или что-то похожее для вашей базы данных.

В качестве альтернативы, вы можете добавить столбец «sort», содержащий целое число.У всех врачей есть 1, у пациентов - 0. Затем вы можете ORDER BY last_name, sort_column, и результаты будут соответствующим образом упорядочены в группе last_name в зависимости от значения сортировки доктора / пациента.

Примечание: сегодня утром я еще не пил свой кофе, так что объединение, возможно, совсем не в порядке, но я надеюсь, что вы поняли основную идею.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...