Resetting counter cache
Ran into a problem whereby the counter cache on one of our associations was out of sync. Simple …just update the counter cache with the count of the association?
rails >> u User.find(1)
rails >> u.update_attribute(:roles_count, 1)
ActiveRecord::ActiveRecordError: roles_count is marked as readonly
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/activerecord-3.2.18/lib/active_record/persistence.rb:194:in `update_column'
from (irb):17
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:47:in `start'
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:8:in `start'
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands.rb:41:in `<top (required)>'
from /data/app/current/script/rails:6:in `require'
from /data/app/current/script/rails:6:in `<main>'
rails >> u.update_column(:roles_count, 1)
ActiveRecord::ActiveRecordError: roles_count is marked as readonly
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/activerecord-3.2.18/lib/active_record/persistence.rb:194:in `update_column'
from (irb):17
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:47:in `start'
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:8:in `start'
from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands.rb:41:in `<top (required)>'
from /data/app/current/script/rails:6:in `require'
from /data/app/current/script/rails:6:in `<main>'
rails pro >> User.readonly_attributes
=> #<Set: {"roles_count"}>
Seems you can’t update the value, I was surprised that update_column wouldn’t work either. I guess it makes sense to protect this value since it’s supposed to be kept in sync and only in rare occasions should it be out of sync. However, you can use the reset_counters class method.
rails >> u = User.find(1)
rails pro >> User.reset_counters u.id, :roles
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
(0.4ms) SELECT COUNT(*) FROM `roles` INNER JOIN `role_users` ON `roles`.`id` = `role_users`.`role_id` WHERE `role_users`.`user_id` = 1
(0.9ms) UPDATE `users` SET `roles_count` = 1 WHERE `users`.`id` = 355411
=> true