以下は Category has_and_belongs_to_many Website な関係が成立しています。HABTMでcounter_cacheを実施するには has_and_belongs_to_manyに:after_add, :after_removeなどのオプションを渡してフックするメソッドをしてあげれば良いです。
そうすることで website.categries = [category_foo, category_bar] としたときに以前のcategoriesとの差分についてcounter_cacheをincrement/decrementしてくれる。
Website自身のフック :after_save, :after_create, :after_destroyは関連を更新したときにはトリガーされないです。
*. #make!はmachinistからデータを作成しています
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> Rails.env | |
# => "test" | |
> c1,c2,c3 = Category.make!,Category.make!,Category.make! | |
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message. | |
(0.4ms) BEGIN | |
test | |
SQL (0.5ms) INSERT INTO `categories` (`created_at`, `description`, `name`, `updated_at`) VALUES ('2014-01-01 04:08:14', 'syndicate strategic web-readiness', 'Books', '2014-01-01 04:08:14') | |
(1.9ms) COMMIT | |
Category Load (0.3ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 16 LIMIT 1 | |
(0.1ms) BEGIN | |
test | |
SQL (0.2ms) INSERT INTO `categories` (`created_at`, `description`, `name`, `updated_at`) VALUES ('2014-01-01 04:08:14', 'enhance clicks-and-mortar bandwidth', 'Electronics & Computers', '2014-01-01 04:08:14') | |
(0.8ms) COMMIT | |
Category Load (0.2ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 17 LIMIT 1 | |
(0.1ms) BEGIN | |
test | |
SQL (0.1ms) INSERT INTO `categories` (`created_at`, `description`, `name`, `updated_at`) VALUES ('2014-01-01 04:08:14', 'leverage front-end synergies', 'Home, Garden & Tools', '2014-01-01 04:08:14') | |
(0.3ms) COMMIT | |
Category Load (0.1ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 18 LIMIT 1 | |
> website = Website.make!(categories: [c1, c2, c3]) | |
SQL (0.7ms) UPDATE `categories` SET `websites_count` = COALESCE(`websites_count`, 0) + 1 WHERE `categories`.`id` = 16 | |
SQL (0.4ms) UPDATE `categories` SET `websites_count` = COALESCE(`websites_count`, 0) + 1 WHERE `categories`.`id` = 17 | |
SQL (0.5ms) UPDATE `categories` SET `websites_count` = COALESCE(`websites_count`, 0) + 1 WHERE `categories`.`id` = 18 | |
(0.2ms) BEGIN | |
SQL (0.3ms) INSERT INTO `websites` (`created_at`, `description`, `likes_count`, `name`, `updated_at`, `url`) VALUES ('2014-01-01 04:08:17', 'engage back-end metrics', 48486642, 'Elmer Pfeffer', '2014-01-01 04:08:17', 'http://runolfonprohaska.name') | |
(0.1ms) INSERT INTO `categories_websites` (`website_id`, `category_id`) VALUES (37, 16) | |
(0.1ms) INSERT INTO `categories_websites` (`website_id`, `category_id`) VALUES (37, 17) | |
(0.1ms) INSERT INTO `categories_websites` (`website_id`, `category_id`) VALUES (37, 18) | |
(0.3ms) COMMIT | |
Website Load (0.2ms) SELECT `websites`.* FROM `websites` WHERE `websites`.`id` = 37 LIMIT 1 | |
=> #<Website id: 37, name: "Elmer Pfeffer", description: "engage back-end metrics", url: "http://runolfonprohaska.name", likes_count: 48486642, comments_count: 0, created_at: "2014-01-01 04:08:17", updated_at: "2014-01-01 04:08:17", logo_file_name: nil, logo_content_type: nil, logo_file_size: nil, logo_updated_at: nil> | |
> website.categories = [c1, c2] | |
Category Load (0.4ms) SELECT `categories`.* FROM `categories` INNER JOIN `categories_websites` ON `categories`.`id` = `categories_websites`.`category_id` WHERE `categories_websites`.`website_id` = 37 | |
(0.1ms) BEGIN | |
(0.2ms) DELETE FROM `categories_websites` WHERE `categories_websites`.`website_id` = 37 AND `categories_websites`.`category_id` IN (18) | |
SQL (0.1ms) UPDATE `categories` SET `websites_count` = COALESCE(`websites_count`, 0) - 1 WHERE `categories`.`id` = 18 | |
(1.5ms) COMMIT | |
=> [#<Category id: 16, name: "Books", description: "syndicate strategic web-readiness", created_at: "2014-01-01 04:08:14", updated_at: "2014-01-01 04:08:14", websites_count: nil>, | |
#<Category id: 17, name: "Electronics & Computers", description: "enhance clicks-and-mortar bandwidth", created_at: "2014-01-01 04:08:14", updated_at: "2014-01-01 04:08:14", websites_count: nil>] | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Website < ActiveRecord::Base | |
has_and_belongs_to_many :categories, after_add: :increment_categories_counter_cache, after_remove: :decrement_categories_counter_cache | |
private | |
def increment_categories_counter_cache(category) | |
Category.increment_counter(:websites_count, category.id ) | |
end | |
def decrement_categories_counter_cache(category) | |
Category.decrement_counter(:websites_count, category.id ) | |
end | |
end |