has_many:通过counter_cache

时间:2012-01-24 17:16:10

标签: ruby-on-rails ruby

我的理解是,在定义:counter_cache选项时,应在包含belongs_to声明的模型上指定它。因此,当使用has_may通过关联时,我有点不确定如何处理这个问题(因为我认为在这种情况下不使用belongs_to声明):

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician, :counter_cache => appointment_count
end

class Patient < ActiveRecord::Base
end

我希望使用:counter_cache选项来更有效地查找属于医生的患者数量。

myPhysician.patients.count

仅供参考:Rails 3.1

干杯

4 个答案:

答案 0 :(得分:26)

我不确定你想要什么样的关系。该示例类似于Rails Guide

中的示例
class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, :through => :appointments
end
  • Physician有许多Appointments,并且有许多Patients
  • Appoinment属于(有一个)Physician和一个Patient
  • Patient有许多Appointments和许多Physicians

关于:counter_cache选项,根据belongs_to doc: 如果您想要Patients属于Physician的数量,则需要:

class Appointment < ActiveRecord::Base
  belongs_to :physician, :counter_cache => :patient_count
  belongs_to :patient
end

您需要编写迁移以将patient_count 列添加到Phyisicans表。

但是,对于has_many通过关系Rails 3.1似乎会自动检测counter_cache列,因此您不必指定它(删除:counter_cache => :patient_count)。如果你指定它,你的计数器会上升两个(这很奇怪)。

顺便说一句,似乎有一些问题:Rails 3.1中的counter_cache选项,如下所示:

考虑到所有这些,也许你最好的选择是使用回调编写自己的计数机制。

希望有所帮助:)

答案 1 :(得分:5)

我在Rails 5.1上为counter_cache关联添加了has_many :through,其理念与has_many相同。使用医师,预约,患者示例:

  1. patients_count添加到physicians表中作为整数
  2. 将计数器缓存添加到连接模型(appointment.rb):belongs_to :physician, counter_cache: :patients_count
  3. 注意:上面的答案是正确的,这个答案只是确认它适用于Rails 5.1。

答案 2 :(得分:0)

我遇到了类似的问题,计算了两种深度关系中的记录数。在您的示例中,这是医师的患者人数,而不是预约的人数。 (例如,不要为一个患者计算多个约会)我没有测试过提供的其他解决方案,但看来它们会返回约会数量。

我发现在Rails 4中无法做到这一点,主要是因为没有belongs_to through:选项。用尽无济于事的方法之后,我发现了gem counter_culture。通过定义要计数的两个深度关系,这很容易解决了这个问题:

class Patient < ActiveRecord::Base
  belongs_to :appointment
  counter_culture [:appointment, :physician]
end

通过以下方式向“医师”添加计数器字段:

rails generate counter_culture Physician patients_count

瞧!您现在可以执行简单的activerecord查询,例如:

Physician.order(patients_count: 'DESC')

答案 3 :(得分:0)

我还可以确认Ivica Lakatos概述的方法可以通过联接模型与Rails 6一起用于has_many :through关系。

  1. 以整数形式将Patients_count添加到医生表中
  2. 将计数器缓存添加到联接模型(appointment.rb): belongs_to :physician, counter_cache: :patients_count