ssc*_*rus 37 ruby-on-rails ruby-on-rails-3
我不熟悉计数器缓存的概念,并且在我的应用程序主页上有一些天文加载时间,我相信我需要继续它.
我需要实现的大多数计数器缓存都附加了某些(简单)条件.例如,这是一个常见的查询:
@projects = employee.projects.where("complete = ?", true).count
Run Code Online (Sandbox Code Playgroud)
N+1当我显示一个列出公司每个员工的项目计数的表单时,我遇到了上面的查询问题.
我真的不知道我在做什么,所以请指正!
# new migration
add_column :employees, :projects_count, :integer, :default => 0, :null => false
# employee.rb
has_many :projects
# project.rb
belongs_to :employee, :counter_cache => true
Run Code Online (Sandbox Code Playgroud)
迁移后...是我需要做的吗?
我如何在我提到的条件下工作,以尽量减少加载时间?
Mik*_*wis 27
关于条件counter_cache,我会阅读这篇博文.
您应该做的一件事是将以下内容添加到迁移文件中:
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
Run Code Online (Sandbox Code Playgroud)
因此,您当前的项目计数可以迁移到projects_count与每个Employee对象关联的新项目.在那之后,你应该好好去.
phi*_*kov 13
检查counter_culture gem:
counter_culture :category, column_name: Proc.new {|project| project.complete? ? 'complete_count' : nil }
Run Code Online (Sandbox Code Playgroud)
您不应该使用"counter_cache"而是使用自定义列:
rails g migration AddCompletedProjectsCountToEmployees completed_projects_count:integer
Run Code Online (Sandbox Code Playgroud)
(, :default => 0如果需要,添加到add_column行)
rake db:migrate
Run Code Online (Sandbox Code Playgroud)
然后使用回调
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
Run Code Online (Sandbox Code Playgroud)
添加列后,您应该在控制台或迁移文件中进行初始化(在def up中):
Employee.all.each &:refresh_completed_projects_count
Run Code Online (Sandbox Code Playgroud)
然后在您的代码中,您应该调用employee.completed_projects_count以访问它
而不是update_counters我用update_all
您不需要这Employee.reset_column_information条线,而且速度更快,因为您正在执行单个数据库调用
Employee.update_all("projects_count = (
SELECT COUNT(projects.id) FROM projects
WHERE projects.employee_id = employees.id AND projects.complete = 't')")
Run Code Online (Sandbox Code Playgroud)