代码之家  ›  专栏  ›  技术社区  ›  Tony

如何按继承自RubyonRails中同一个基类的多个子类的属性排序?

  •  2
  • Tony  · 技术社区  · 16 年前

    我有4个班——病人、医生、病人和预约。病人和医生是人的子类。预约属于病人和医生。

    我想写一个AR语句,按病人的姓氏对预约进行排序,另一个语句按医生的姓氏排序,因为所有的预约都在一个可排序的表中。关于ar find语句的“order”选项中要放入什么,我有点困惑。如果我放

    :order => 'patient.last_name'
    

    我得到一个mysql错误-“未知列”patient.last“name” 这很有意义,因为没有“患者”列,它是一个患者ID,指的是一个外来的“人”对象。当然,我可以按人名进行排序,但我不知道如何指定要按医生或病人进行排序的人。

    我还应该注意,我正在使用include选项来急切地加载患者和医生。

    更新

    只有个人表和预约表。病人和医生都是继承人。patients.last\u名称将不起作用,因为没有患者表。

    AR声明是:

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

    “这里需要做的事情”应该是一个声明,按照医生的姓或病人的姓来排序。

    2 回复  |  直到 16 年前
        1
  •  1
  •   Jaime Bellmyer    16 年前

    您可以这样做:

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

    你要做的就是同时抓住所有的预约和他们的相关病人。你不必担心病人和医生之间的关系,因为所有检索到的人行都是病人记录。

    为了有一个以医生为中心的列表,只需在上面的示例中更改:patient to:doctor。

    编辑:当你急着给病人和医生装药时,我就想出了解决办法。它变得有点复杂。首先,我在一个空白的Rails应用程序中重新创建了4个模型的简单版本,然后尝试使用 :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”。随后的关联会得到关联和原始表的组合-“医生预约”。

    可能看起来有点乱,但这个电话让您按病人的顺序进行:

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

    这个给你的是医生的命令:

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

    当然,在我的示例中,我只是为每个人提供了一个简单的名称字段,而您将使用“姓氏”。但你明白了。这对你有用吗?

    最后一个编辑:

    我将把这些放在finders中,这样您就不必在代码中的任何地方乱用表名了。我会这样做:

    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
    

    现在,您可以从任何地方调用它们,甚至可以根据需要的字段进行排序。

        2
  •  0
  •   Toby Hede    16 年前

    我认为您可能需要使用手动联接而不是include。

    Active Record Querying Guide on Joining Tables .

    然后,您可以为表名创建别名,并相应地对这些别名进行排序。

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

    或者类似的数据库。

    或者,您可以添加一个包含整数的“排序”列。所有医生都有1,病人有0。然后,您可以按姓氏、排序列排序,结果将根据医生/患者排序值在姓氏组中进行相应排列。

    注意:今天早上我还没有喝咖啡,所以加入可能完全是疯了,但你得到了我希望的一般想法。

    推荐文章