It is my understanding that when defining a :counter_cache option it is to be specified on the model that includes the belongs_to declaration. So I am a little unsure of how
I added a counter_cache
to a has_many :through
association on Rails 5.1, and the philosophy is the same as with has_many
. Using the Physician, Appointment, Patient example:
patients_count
to the physicians
table as an integerbelongs_to :physician, counter_cache: :patients_count
Note: the answer above is correct, this answer just confirms that it works on Rails 5.1.
I'm not sure what kind of relationship you want. That example is similar to the one in the 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
has many Appointments
, and has many Patients
Appoinment
belongs to (has one) Physician
and one Patient
Patient
has many Appointments
and many Physicians
.Regarding the :counter_cache option, according to the belongs_to doc:
If you want the number of Patients
belonging to a Physician
you would need:
class Appointment < ActiveRecord::Base
belongs_to :physician, :counter_cache => :patient_count
belongs_to :patient
end
And you need to write a migration to add the patient_count column to the Phyisicans
table.
However, for has_many through relationships Rails 3.1 seems to automatically detect the counter_cache column, so you don't have to specify it (remove :counter_cache => :patient_count
). If you do specify it your counter will go up by two (this is very weird).
By the way, there seems to be some problems with :counter_cache option in Rails 3.1, as reported here:
With all of that in mind, maybe your best bet is to write your own count mechanism using callbacks.
Hope it helps :)
I can also confirm that the method outlined by Ivica Lakatos works with Rails 6 for has_many :through
relationships using a join model.
belongs_to :physician, counter_cache: :patients_count
I ran into a similar problem, counting the number of records in a two-deep relationship. In your example, this would be the number of Patients for a Physician, as opposed to the number of Appointments. (e.g. don't count multiple appointments for one patient) I haven't tested the other solutions offered, but it appears they return the number of appointments.
I found no way to do this in Rails 4, primarily because there is no belongs_to through:
option. After exhausting several fruitless approaches, I found gem counter_culture
. This solved the problem easily, by defining a two-deep relationship to be counted:
class Patient < ActiveRecord::Base
belongs_to :appointment
counter_culture [:appointment, :physician]
end
Add a counter field to Physician with:
rails generate counter_culture Physician patients_count
And voila! You can now do easy activerecord queries like:
Physician.order(patients_count: 'DESC')