I am new to the concept of counter caching and with some astronomical load times on one of my app\'s main pages, I believe I need to get going on it.
Most of the coun
You should not use "counter_cache" but rather a custom column :
rails g migration AddCompletedProjectsCountToEmployees completed_projects_count:integer
(add , :default => 0
to the add_column line if you want)
rake db:migrate
then use callbacks
class Project < ActiveRecord::Base
belongs_to :employee
after_save :refresh_employee_completed_projects_count
after_destroy :refresh_employee_completed_projects_count
def refresh_employee_completed_projects_count
employee.refresh_completed_projects_count
end
end
class Employee
has_many :projects
def refresh_completed_projects_count
update(completed_projects_count:projects.where(completed:true).size)
end
end
After adding the column, you should initialize in the console or in the migration file (in def up) :
Employee.all.each &:refresh_completed_projects_count
Then in your code, you should call employee.completed_projects_count
in order to access it
Check counter_culture gem:
counter_culture :category, column_name: Proc.new {|project| project.complete? ? 'complete_count' : nil }
Instead of update_counters
i use update_all
You don't need the Employee.reset_column_information
line AND it's faster because you are doing a single database call
Employee.update_all("projects_count = (
SELECT COUNT(projects.id) FROM projects
WHERE projects.employee_id = employees.id AND projects.complete = 't')")
With regards to the conditions with counter_cache
, I would read this blog post.
The one thing you should do is add the following to the migration file:
add_column :employees, :projects_count, :integer, :default => 0, :null => false
Employee.reset_column_information
Employee.all.each do |e|
Employee.update_counters e.id, :projects_count => e.projects.length
end
So you current projects count can get migrated to the new projects_count
that are associated with each Employee object. After that, you should be good to go.