Has_many: через counter_cache

Насколько я понимаю, при определении параметра: 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

FYI: Rails 3.1

Приветствия

Ответы

Ответ 1

Я не уверен, какие отношения вы хотите. Этот пример аналогичен приведенному в 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
  • A Physician имеет много Appointments и имеет много Patients
  • An Appoinment принадлежит (имеет один) Physician и один Patient
  • a Patient имеет много Appointments и много Physicians.

Что касается опции: counter_cache, в соответствии с принадлежностью к 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). Если вы укажете его, ваш счетчик увеличится на два (это очень странно).

Кстати, кажется, есть некоторые проблемы с: параметром counter_cache в Rails 3.1, как указано здесь:

Учитывая все это, может быть, лучше всего написать собственный механизм счета с помощью обратных вызовов.

Надеюсь, это поможет:)

Ответ 2

Я добавил counter_cache в has_many :through ассоциации на Rails 5.1, и философия та же, что и для has_many. Пример использования врача, назначения, пациента:

  1. добавьте в таблицу physicians целое число patients_count в виде целого числа
  2. добавьте кеш счетчика в модель соединения (назначение .rb): belongs_to :physician, counter_cache: :patients_count

Примечание: ответ выше верен, этот ответ только подтверждает, что он работает на Rails 5.1.

Ответ 3

Я столкнулся с аналогичной проблемой, считая количество записей в двух глубоких отношениях. В вашем примере это будет количество пациентов для врача, а не количество назначений. (например, не считайте несколько назначений для одного пациента) Я не тестировал другие предлагаемые решения, но, похоже, они возвращают количество назначений.

Я не нашел способа сделать это в Rails 4, в первую очередь потому, что здесь нет belongs_to through: После исчерпания нескольких бесплодных подходов я нашел gem counter_culture. Это легко решило проблему, определив два глубоких отношения, которые нужно посчитать:

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

Добавьте поле счетчика в Physician с помощью:

rails generate counter_culture Physician patients_count

И вуаля! Теперь вы можете легко выполнять запросы activerecord, такие как:

Physician.order(patients_count: 'DESC')