counter_culture 1.8.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +65 -0
  3. data/.travis.yml +27 -9
  4. data/Appraisals +22 -0
  5. data/CHANGELOG.md +169 -0
  6. data/Gemfile +6 -41
  7. data/README.md +142 -21
  8. data/Rakefile +7 -34
  9. data/counter_culture.gemspec +39 -168
  10. data/gemfiles/rails_4.2.gemfile +10 -0
  11. data/gemfiles/rails_5.0.gemfile +10 -0
  12. data/gemfiles/rails_5.1.gemfile +10 -0
  13. data/gemfiles/rails_5.2.gemfile +10 -0
  14. data/gemfiles/rails_6.0.gemfile +10 -0
  15. data/lib/counter_culture.rb +1 -1
  16. data/lib/counter_culture/counter.rb +56 -38
  17. data/lib/counter_culture/extensions.rb +58 -48
  18. data/lib/counter_culture/reconciler.rb +83 -13
  19. data/lib/counter_culture/version.rb +3 -0
  20. data/lib/generators/counter_culture_generator.rb +7 -1
  21. data/lib/generators/templates/counter_culture_migration.rb.erb +6 -12
  22. data/run_tests_locally.sh +20 -0
  23. metadata +100 -131
  24. data/VERSION +0 -1
  25. data/spec/counter_culture_spec.rb +0 -1857
  26. data/spec/models/another_post.rb +0 -13
  27. data/spec/models/another_post_comment.rb +0 -4
  28. data/spec/models/candidate.rb +0 -3
  29. data/spec/models/candidate_profile.rb +0 -3
  30. data/spec/models/categ.rb +0 -13
  31. data/spec/models/category.rb +0 -3
  32. data/spec/models/company.rb +0 -11
  33. data/spec/models/conditional_dependent.rb +0 -7
  34. data/spec/models/conditional_main.rb +0 -3
  35. data/spec/models/conversation.rb +0 -4
  36. data/spec/models/has_string_id.rb +0 -4
  37. data/spec/models/industry.rb +0 -2
  38. data/spec/models/person.rb +0 -4
  39. data/spec/models/poly_employee.rb +0 -3
  40. data/spec/models/poly_image.rb +0 -15
  41. data/spec/models/poly_product.rb +0 -4
  42. data/spec/models/post.rb +0 -10
  43. data/spec/models/post_comment.rb +0 -6
  44. data/spec/models/product.rb +0 -7
  45. data/spec/models/review.rb +0 -33
  46. data/spec/models/simple_dependent.rb +0 -5
  47. data/spec/models/simple_main.rb +0 -3
  48. data/spec/models/simple_review.rb +0 -3
  49. data/spec/models/soft_delete.rb +0 -6
  50. data/spec/models/subcateg.rb +0 -14
  51. data/spec/models/transaction.rb +0 -15
  52. data/spec/models/twitter_review.rb +0 -6
  53. data/spec/models/user.rb +0 -40
  54. data/spec/rails_app/.gitignore +0 -15
  55. data/spec/rails_app/Gemfile +0 -41
  56. data/spec/rails_app/Gemfile.lock +0 -150
  57. data/spec/rails_app/README.rdoc +0 -261
  58. data/spec/rails_app/Rakefile +0 -7
  59. data/spec/rails_app/app/assets/images/rails.png +0 -0
  60. data/spec/rails_app/app/assets/javascripts/application.js +0 -15
  61. data/spec/rails_app/app/assets/stylesheets/application.css +0 -13
  62. data/spec/rails_app/app/controllers/application_controller.rb +0 -3
  63. data/spec/rails_app/app/helpers/application_helper.rb +0 -2
  64. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  65. data/spec/rails_app/app/models/.gitkeep +0 -0
  66. data/spec/rails_app/app/views/layouts/application.html.erb +0 -14
  67. data/spec/rails_app/config.ru +0 -4
  68. data/spec/rails_app/config/application.rb +0 -58
  69. data/spec/rails_app/config/boot.rb +0 -6
  70. data/spec/rails_app/config/database.yml +0 -25
  71. data/spec/rails_app/config/environment.rb +0 -5
  72. data/spec/rails_app/config/environments/development.rb +0 -32
  73. data/spec/rails_app/config/environments/test.rb +0 -31
  74. data/spec/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  75. data/spec/rails_app/config/initializers/inflections.rb +0 -15
  76. data/spec/rails_app/config/initializers/mime_types.rb +0 -5
  77. data/spec/rails_app/config/initializers/paper_trail.rb +0 -1
  78. data/spec/rails_app/config/initializers/secret_token.rb +0 -7
  79. data/spec/rails_app/config/initializers/session_store.rb +0 -8
  80. data/spec/rails_app/config/initializers/wrap_parameters.rb +0 -14
  81. data/spec/rails_app/config/locales/en.yml +0 -5
  82. data/spec/rails_app/config/routes.rb +0 -58
  83. data/spec/rails_app/db/seeds.rb +0 -7
  84. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  85. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  86. data/spec/rails_app/log/.gitkeep +0 -0
  87. data/spec/rails_app/public/404.html +0 -26
  88. data/spec/rails_app/public/422.html +0 -26
  89. data/spec/rails_app/public/500.html +0 -25
  90. data/spec/rails_app/public/favicon.ico +0 -0
  91. data/spec/rails_app/public/index.html +0 -241
  92. data/spec/rails_app/public/robots.txt +0 -5
  93. data/spec/rails_app/script/rails +0 -6
  94. data/spec/rails_app/test/fixtures/.gitkeep +0 -0
  95. data/spec/rails_app/test/functional/.gitkeep +0 -0
  96. data/spec/rails_app/test/integration/.gitkeep +0 -0
  97. data/spec/rails_app/test/performance/browsing_test.rb +0 -12
  98. data/spec/rails_app/test/test_helper.rb +0 -13
  99. data/spec/rails_app/test/unit/.gitkeep +0 -0
  100. data/spec/rails_app/vendor/assets/javascripts/.gitkeep +0 -0
  101. data/spec/rails_app/vendor/assets/stylesheets/.gitkeep +0 -0
  102. data/spec/rails_app/vendor/plugins/.gitkeep +0 -0
  103. data/spec/schema.rb +0 -227
  104. data/spec/spec_helper.rb +0 -32
  105. data/test_rails_versions.sh +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d2851375f488ec2d44fad34f75bc463cc7b6d30e
4
- data.tar.gz: e8cee5f97368554bd04a0acc97b9feffb7e9fe5c
2
+ SHA256:
3
+ metadata.gz: 74fff95505913ba522b3ec93bc9101c375c7de5678744145a0e4959f2c267361
4
+ data.tar.gz: bc284f87da6f949e7d875b7f30c43accbe23ce5716601af9fc4143eb6346954d
5
5
  SHA512:
6
- metadata.gz: b6af5865d97f22a07be30100266b5b2ee67778c9447c3e74e45c82d21e268912f83d295431cc4ad5ed26d3cc86eee95277a846044b9247ef61b238e6b98ac411
7
- data.tar.gz: f8ac7e975612ddb98bb955b090db7d29511b602797fa3d684a1743a1d000f95e8a5bd8d2c0b6092c8a6cec236cd932a7437517e2da33c2e39c5e64e69d21fbca
6
+ metadata.gz: e63708745c4ffbb727a1b4da61a0d027de76d7256ee5d9669fa0f18dfcc2b183f26ddc109f45d6af6fb68a79c040e73872f647e8453c7b801e390036601878eb
7
+ data.tar.gz: c58c36d4aaf450450d913ad93487c7012de5de0ba8bb4f99c83a3994b64e8aed19f04a0d62c0df21ceda862312b9c010af042857709d891f746e20403ef893f2
@@ -0,0 +1,65 @@
1
+ # appraisal lockfiles
2
+ gemfiles/*.lock
3
+
4
+ # spec coverage
5
+ coverage
6
+ coverage.data
7
+
8
+ # rdoc generated
9
+ rdoc
10
+
11
+ # yard generated
12
+ doc
13
+ .yardoc
14
+
15
+ # bundler
16
+ .bundle
17
+
18
+ # jeweler generated
19
+ pkg
20
+
21
+ # this changes all the time when we change multiple Rails versions
22
+ Gemfile.lock
23
+
24
+ # allow people to manage their own Ruby versions / gemsets
25
+ .ruby-version
26
+ .ruby-gemset
27
+
28
+ # rspec pass/fail status
29
+ .rspec_status
30
+
31
+ # sqlite3 db
32
+ db
33
+
34
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
35
+ #
36
+ # * Create a file at ~/.gitignore
37
+ # * Include files you want ignored
38
+ # * Run: git config --global core.excludesfile ~/.gitignore
39
+ #
40
+ # After doing this, these files will be ignored in all your git projects,
41
+ # saving you from having to 'pollute' every project you touch with them
42
+ #
43
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
44
+ #
45
+ # For MacOS:
46
+ #
47
+ #.DS_Store
48
+
49
+ # For TextMate
50
+ #*.tmproj
51
+ #tmtags
52
+
53
+ # For emacs:
54
+ #*~
55
+ #\#*
56
+ #.\#*
57
+
58
+ # For vim:
59
+ #*.swp
60
+
61
+ # For redcar:
62
+ #.redcar
63
+
64
+ # For rubinius:
65
+ #*.rbc
@@ -1,14 +1,32 @@
1
1
  language: ruby
2
+ services:
3
+ - postgresql
4
+ - mysql
5
+ addons:
6
+ postgresql: "9.6"
2
7
  rvm:
3
- - "2.2.5"
4
- - "2.3.1"
8
+ - "2.5.7"
9
+ - "2.6.5"
10
+ - "2.7.0"
11
+ gemfile:
12
+ - gemfiles/rails_4.2.gemfile
13
+ - gemfiles/rails_5.0.gemfile
14
+ - gemfiles/rails_5.1.gemfile
15
+ - gemfiles/rails_5.2.gemfile
16
+ - gemfiles/rails_6.0.gemfile
17
+ matrix:
18
+ exclude:
19
+ - rvm: "2.7.0"
20
+ gemfile: gemfiles/rails_4.2.gemfile
5
21
  env:
6
- - "RAILS_VERSION=3.2.0"
7
- - "RAILS_VERSION=4.0.0"
8
- - "RAILS_VERSION=4.1.0"
9
- - "RAILS_VERSION=4.2.0"
10
- - "RAILS_VERSION=5.0.0"
11
- - "RAILS_VERSION=5.1.0"
22
+ - DB=postgresql
23
+ - DB=sqlite3
24
+ - DB=mysql2
25
+ before_install:
26
+ - gem install bundler -v '1.17.3'
12
27
  install:
13
- - bundle update
28
+ - bundle _1.17.3_ update
29
+ before_script:
30
+ - psql -c 'create database counter_culture_test;' -U postgres
31
+ - mysql -e 'CREATE DATABASE counter_culture_test;'
14
32
  script: TRAVIS=true bundle exec rake spec
@@ -0,0 +1,22 @@
1
+ %w[
2
+ 4.2
3
+ 5.0
4
+ 5.1
5
+ 5.2
6
+ 6.0
7
+ ].each do |rails_version|
8
+ gem_rails_version = Gem::Version.new(rails_version)
9
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0') &&
10
+ gem_rails_version >= Gem::Version.new('6.0.0.beta')
11
+
12
+ # Rails 6 requires Ruby >= 2.5
13
+ next
14
+ end
15
+ appraise "rails-#{rails_version}" do
16
+ gem 'rails', "~> #{rails_version}.0"
17
+
18
+ gem 'pg', gem_rails_version < Gem::Version.new('5.0') ? '~> 0.15' : '~> 1.0'
19
+ gem 'mysql2'
20
+ gem 'sqlite3', gem_rails_version < Gem::Version.new(5.2) ? '~> 1.3.0' : '~> 1.4'
21
+ end
22
+ end
@@ -1,3 +1,172 @@
1
+ ## 2.7.0 (November 16, 2020)
2
+
3
+ Improvements:
4
+ - New `column_name` option for `counter_culture_fix_counts` (#300)
5
+
6
+ ## 2.6.2 (October 21, 2020)
7
+
8
+ Improvements:
9
+ - Remove superfluous dependency to after_commit_action gem (#297)
10
+
11
+ ## 2.6.1 (September 8, 2020)
12
+
13
+ Bugfixes:
14
+ - Address Ruby 2.7.0 deprecation warning (#292)
15
+
16
+ ## 2.6.0 (July 29, 2020)
17
+
18
+ Improvements:
19
+ - Use []= method instead of attribute writer method internally to avoid conflicts with read-only attributes (#287)
20
+ - More detailed logging when performing reconciliation (#288)
21
+
22
+ ## 2.5.1 (May 18, 2020)
23
+
24
+ Bugfixes:
25
+ - Fix migration generation in Rails 6+ (#281)
26
+
27
+ ## 2.5.0 (May 12, 2020)
28
+
29
+ Bugfixes:
30
+ - Fix `counter_culture_fix_counts` with Rails 4.2
31
+
32
+ Changes:
33
+ - Dropped support for Ruby 2.3 and 2.4
34
+
35
+ ## 2.4.0 (May 9, 2020)
36
+
37
+ Improvements:
38
+ - Allow specifying `start` and `finish` options to `counter_culture_fix_counts` (#279)
39
+
40
+ ## 2.3.0 (January 28, 2020)
41
+
42
+ Improvements:
43
+ - Allow using scopes in `column_names` (#272)
44
+
45
+ ## 2.2.4 (August 21, 2019)
46
+
47
+ Bugfixes:
48
+ - Test and fix behavior in Rails 6.0.0 release (#268)
49
+
50
+ ## 2.2.3 (June 20, 2019)
51
+
52
+ Improvements:
53
+ - Start testing against MySQL and PostgreSQL as well as sqlite3 (#257)
54
+
55
+ Bugfixes:
56
+ - Fix edge cases in MySQL (#257)
57
+
58
+ ## 2.2.2 (May 5, 2019)
59
+
60
+ Bugfixes:
61
+ - Don't fail reconciliation in PostgreSQL if the Rails-level primary key is not a DB primary key (#254)
62
+
63
+ ## 2.2.1 (April 17, 2019)
64
+
65
+ Improvements:
66
+ - Improve logging when `verbose` is set (#256)
67
+
68
+ ## 2.2.0 (April 9, 2019)
69
+
70
+ Improvements:
71
+ - Add `where` option to `counter_culture_fix_counts` (#250)
72
+ - Add `verbose` option to `counter_culture_fix_counts` (#251)
73
+
74
+ Changes:
75
+ - Dropped support for Ruby 2.2
76
+ - Dropped support for Rails 3.2, 4.0 and 4.1
77
+
78
+ ## 2.1.4 (January 21, 2019)
79
+
80
+ Improvements:
81
+ - Avoid instantiating model class during `counter_culture` call (#246)
82
+
83
+ ## 2.1.3 (January 19, 2019)
84
+
85
+ Bugfixes:
86
+ - Don't update running total on soft-deleted records (#244)
87
+
88
+ ## 2.1.2 (December 7, 2018)
89
+
90
+ Bugfixes:
91
+ - Properly handle `destroy` and `really_destroy` when using Paranoia (#239)
92
+
93
+ ## 2.1.1 (November 7, 2018)
94
+
95
+ Bugfixes:
96
+ - Don't double-decrement when discarding and then hard-destroying a record (#237)
97
+
98
+ ## 2.1.0 (October 19, 2018)
99
+
100
+ Bugfixes:
101
+ - Fix behavior with Models that are part of a module (ex: `Users::Admin`) (#234)
102
+
103
+ ## 2.0.1 (August 19, 2018)
104
+
105
+ Bugfixes:
106
+ - Properly set timestamps of PaperTrail versions (#224, #225, #226)
107
+
108
+ ## 2.0.0 (June 12, 2018)
109
+
110
+ Breaking changes:
111
+ - execute_after_commit was removed
112
+ - Removed workaround for incorrect counts when triggering updates from an `after_create` hook. Your options if this applies to you:
113
+ * continue using counter_culture 1.12.0
114
+ * upgrade to Rails 5.1.5 which fixes the underlying issue in Rails
115
+ * avoid triggering further updates on the same model in `after_create`; simply set the attribute in `before_create` instead
116
+
117
+ Bugfixes:
118
+ - Multiple updates in one transaction will now be processed correctly (#222)
119
+
120
+ ## 1.12.0 (June 8, 2018)
121
+
122
+ Improvements:
123
+ - Adds support for the [Discard](https://github.com/jhawthorn/discard) soft-delete gem (#220)
124
+
125
+ ## 1.11.0 (May 4, 2018)
126
+
127
+ Bugfixes:
128
+ - Fix `with_papertrail` behavior while still addressing the deprecation warning, and actually recording the correct counts (#218, see [airblade/paper_trail#1076](https://github.com/airblade/paper_trail/issues/1076))
129
+
130
+ ## 1.10.1 (April 20, 2018)
131
+
132
+ Improvements:
133
+ - Added the ability to update timestamps while fixing count by passing `touch: true` to `counter_culture_fix_counts` (#212)
134
+
135
+ ## 1.9.2 (April 13, 2018)
136
+
137
+ Bugfixes:
138
+ - When using paranoia, call increment / decrement only once when calling destroy or restore on the same model multiple times
139
+
140
+ Improvements:
141
+ - Address deprecation warning when enabling paper_trail touch in paper_trail version 9.0
142
+ - Address `Arel` deprecation warnings in Rails 5.2
143
+
144
+ Changes:
145
+ - Test against Ruby 2.2 through 2.5, Rails 3.2 through 5.2
146
+ - Don't test Rails 3.2 through 4.1 against Ruby 2.4 or 2.5 as those versions of Rails will not work with those versions of Ruby
147
+ - Avoid various deprecation warnings being triggered in the test
148
+
149
+ ## 1.9.1 (March 1, 2018)
150
+
151
+ Bugfixes:
152
+ - Address an edge-case test regression caused by Rails 5.1.5 that was causing counts to be off when saving changes from an `after_create` callback
153
+
154
+ ## 1.9.0 (November 29, 2017)
155
+
156
+ Improvements:
157
+ - Switch generated migration files to use new hash syntax
158
+ - Support for Rails 5 migration file format for generated migrations
159
+
160
+ ## 1.8.2 (September 27, 2017)
161
+
162
+ Bugfixes:
163
+ - Actually use `batch_size` parameter in `counter_culture_fix_counts` (#200)
164
+
165
+ ## 1.8.1 (September 5, 2017)
166
+
167
+ Improvements:
168
+ - Use ActiveRecord version, not Rails version, in `Reconciler`, makeing it possible to use `counter_culture_fix_counts` without Rails
169
+
1
170
  ## 1.8.0 (August 30, 2017)
2
171
 
3
172
  Improvements:
data/Gemfile CHANGED
@@ -1,44 +1,9 @@
1
- source "https://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
1
+ source 'https://rubygems.org'
5
2
 
6
- gem "after_commit_action", "~> 1.0"
7
- gem "activerecord", ">= 3.0.0"
8
- gem "activesupport", ">= 3.0.0"
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
9
4
 
10
- # Add dependencies to develop your gem here.
11
- # Include everything needed to run rake, tests, features, etc.
12
- group :development, :test do
13
- gem "rake"
5
+ # Specify the gem's dependencies in counter_culture.gemspec
6
+ gemspec
14
7
 
15
- rails = case ENV["RAILS_VERSION"]
16
- when "master"
17
- {github: "rails/rails"}
18
- when nil, ""
19
- ">= 3.1.0"
20
- else
21
- "~> #{ENV["RAILS_VERSION"]}"
22
- end
23
- gem "rails", rails
24
-
25
- gem "rspec", "~> 3.0"
26
- gem "awesome_print"
27
- gem "timecop"
28
-
29
- # to test the integration
30
- gem "paranoia"
31
- gem "paper_trail"
32
- end
33
-
34
- group :development do
35
- gem "rdoc", "~> 3.12"
36
- gem "bundler", ">= 1.2.0"
37
- gem "jeweler", "~> 2.1"
38
- end
39
-
40
- group :test do
41
- gem "sqlite3"
42
- gem "rspec-extra-formatters"
43
- gem "database_cleaner", ">= 1.1.1"
44
- end
8
+ # Ensure we have the default DB adapter for testing
9
+ gem 'sqlite3'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # counter_culture [![Build Status](https://travis-ci.org/magnusvk/counter_culture.svg)](https://travis-ci.org/magnusvk/counter_culture)
1
+ # counter_culture [![Build Status](https://travis-ci.com/magnusvk/counter_culture.svg)](https://travis-ci.com/magnusvk/counter_culture)
2
2
 
3
3
  Turbo-charged counter caches for your Rails app. Huge improvements over the Rails standard counter caches:
4
4
 
@@ -7,14 +7,20 @@ Turbo-charged counter caches for your Rails app. Huge improvements over the Rail
7
7
  * Supports dynamic column names, making it possible to split up the counter cache for different types of objects
8
8
  * Can keep a running count, or a running total
9
9
 
10
- Tested against Ruby 2.2.5 and 2.3.1 and against the latest patch releases of Rails 3.2, 4.0, 4.1, 4.2, 5.0 and 5.1.
10
+ Tested against Ruby 2.3.8, 2.4.7, 2.5.6 and 2.6.4 and against the latest patch releases of Rails 4.2, 5.0, 5.1, 5.2 and 6.0.
11
+
12
+ Please note that -- unlike Rails' built-in counter-caches -- counter_culture does not currently change the behavior of the `.size` method on ActiveRecord associations. If you want to avoid a database query and read the cached value, please use the attribute name containing the counter cache directly.
13
+ ```
14
+ product.categories.size # => will lead to a SELECT COUNT(*) query
15
+ product.categories_count # => will use counter cache without query
16
+ ```
11
17
 
12
18
  ## Installation
13
19
 
14
20
  Add counter_culture to your Gemfile:
15
21
 
16
22
  ```ruby
17
- gem 'counter_culture', '~> 1.0'
23
+ gem 'counter_culture', '~> 2.0'
18
24
  ```
19
25
 
20
26
  Then run `bundle install`
@@ -39,6 +45,8 @@ If you are adding counter caches to existing data, you must add code to [manuall
39
45
 
40
46
  ### Simple counter-cache
41
47
 
48
+ #### Has many association
49
+
42
50
  ```ruby
43
51
  class Product < ActiveRecord::Base
44
52
  belongs_to :category
@@ -52,6 +60,30 @@ end
52
60
 
53
61
  Now, the ```Category``` model will keep an up-to-date counter-cache in the ```products_count``` column of the ```categories``` table.
54
62
 
63
+ #### Many to many association
64
+
65
+ ```ruby
66
+ class User < ActiveRecord::Base
67
+ has_many :group_memberships
68
+ has_many :groups, through: :group_memberships
69
+ end
70
+
71
+ class Group < ActiveRecord::Base
72
+ has_many :group_memberships
73
+ has_many :members, through: :group_memberships, class: "User"
74
+ end
75
+
76
+ class Membership < ActiveRecord::Base
77
+ belongs_to :group
78
+ belongs_to :member, class: "User"
79
+ counter_culture :group, column_name: "members_count"
80
+ # If you'd like to also touch the group when `members_count` is updated
81
+ # counter_culture :group, column_name: "members_count", touch: true
82
+ end
83
+ ```
84
+
85
+ Now, the `Group` model will have an up to date count of its members in the `members_count` column
86
+
55
87
  ### Multi-level counter-cache
56
88
 
57
89
  ```ruby
@@ -116,7 +148,7 @@ end
116
148
  ```ruby
117
149
  class Product < ActiveRecord::Base
118
150
  belongs_to :category
119
- counter_culture :category, column_name: :weight, delta_magnitude: proc { model.product_type == 'awesome' ? 2 : 1 }
151
+ counter_culture :category, column_name: :weight, delta_magnitude: proc {|model| model.product_type == 'awesome' ? 2 : 1 }
120
152
  end
121
153
 
122
154
  class Category < ActiveRecord::Base
@@ -155,6 +187,8 @@ end
155
187
 
156
188
  Now, the ```Category``` model will keep the counter cache in ```special_count``` up-to-date. Only products where ```special?``` returns true will affect the special_count.
157
189
 
190
+ If you would like to use this with `counter_culture_fix_counts`, make sure to also provide [the `column_names` configuration](#handling-dynamic-column-names).
191
+
158
192
  ### Totaling instead of counting
159
193
 
160
194
  Instead of keeping a running count, you may want to automatically track a running total.
@@ -216,16 +250,6 @@ You may also specify a custom timestamp column that gets updated only when a par
216
250
 
217
251
  With this option, any time the `category_counter_cache` changes both the `category_count_changed` and `updated_at` columns will get updated.
218
252
 
219
- ### Executing counter cache updates after commit
220
-
221
- By default, counter_culture will run counter cache updates inside of the same ActiveRecord transaction that triggered it. (Note that this bevavior [changed from version 0.2.3 to 1.0.0](CHANGELOG.md#100-november-15-2016).) If you would like to run counter cache updates outside of that transaction, for example because you are experiencing [deadlocks with older versions of PostgreSQL](http://mina.naguib.ca/blog/2010/11/22/postgresql-foreign-key-deadlocks.html), you can enable that behavior:
222
- ```ruby
223
- counter_culture :category, execute_after_commit: true
224
- ```
225
-
226
- Please note that using `execute_after_commit` in conjunction with transactional
227
- fixtures will lead to your tests no longer seeing updated counter values.
228
-
229
253
  ### Manually populating counter cache values
230
254
 
231
255
  You will sometimes want to populate counter-cache values from primary data. This is required when adding counter-caches to existing data. It is also recommended to run this regularly (at BestVendor, we run it once a week) to catch any incorrect values in the counter caches.
@@ -234,19 +258,29 @@ You will sometimes want to populate counter-cache values from primary data. This
234
258
  Product.counter_culture_fix_counts
235
259
  # will automatically fix counts for all counter caches defined on Product
236
260
 
237
- Product.counter_culture_fix_counts except: :category
261
+ Product.counter_culture_fix_counts exclude: :category
238
262
  # will automatically fix counts for all counter caches defined on Product, except for the :category relation
239
263
 
240
264
  Product.counter_culture_fix_counts only: :category
241
265
  # will automatically fix counts only on the :category relation on Product
242
266
 
243
- # :except and :only also accept arrays of one level relations
267
+ # :exclude and :only also accept arrays of one level relations
244
268
  # if you want to fix counts on a more than one level relation you need to use convention below:
245
269
 
246
270
  Product.counter_culture_fix_counts only: [[:subcategory, :category]]
247
271
  # will automatically fix counts only on the two-level [:subcategory, :category] relation on Product
248
272
 
273
+ Product.counter_culture_fix_counts column_name: :reviews_count
274
+ # will automatically fix counts only on the :reviews_count column on Product
275
+ # This allows us to skip the columns that have already been processed. This is useful after running big DB changes that affect only one counter cache column.
276
+
249
277
  # :except and :only also accept arrays
278
+
279
+ Product.counter_culture_fix_counts verbose: true
280
+ # prints some logs to STDOUT
281
+
282
+ Product.counter_culture_fix_counts only: :category, where: { categories: { id: 1 } }
283
+ # will automatically fix counts only on the :category with id 1 relation on Product
250
284
  ```
251
285
 
252
286
  The ```counter_culture_fix_counts``` counts method uses batch processing of records to keep the memory consumption low. The default batch size is 1000 but is configurable like so
@@ -272,6 +306,37 @@ Product.counter_culture_fix_counts batch_size: 100
272
306
 
273
307
  ```counter_culture_fix_counts``` is optimized to minimize the number of queries and runs very quickly.
274
308
 
309
+ Similarly to `counter_culture`, it is possible to update the records' timestamps, when fixing counts. If you would like to update the default timestamp field, pass `touch: true` option:
310
+
311
+ ```ruby
312
+ Product.counter_culture_fix_counts touch: true
313
+ ```
314
+
315
+ If you have specified a custom timestamps column, pass its name as the value for the `touch` option:
316
+
317
+ ```ruby
318
+ Product.counter_culture_fix_counts touch: 'category_count_changed'
319
+ ```
320
+
321
+
322
+ #### Parallelizing fix counter cache in multiple workers
323
+
324
+ The options start and finish are especially useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the records between id 1 and 9999 and worker 2 handle from 10000 and beyond by setting the :start and :finish option on each worker.
325
+
326
+ ```ruby
327
+ Product.counter_culture_fix_counts start: 10_000
328
+ # will fix counts for all counter caches defined on Product from record 10000 and onwards.
329
+
330
+ Product.counter_culture_fix_counts finish: 10_000
331
+ # let's process until 10000 records.
332
+
333
+ Product.counter_culture_fix_counts start: 1000, finish: 2000
334
+ # In worker 1, lets process from 1000 to 2000
335
+
336
+ Product.counter_culture_fix_counts start: 2001, finish: 3000
337
+ # In worker 2, lets process from 2001 to 3000
338
+ ```
339
+
275
340
  #### Handling dynamic column names
276
341
 
277
342
  Manually populating counter caches with dynamic column names requires additional configuration:
@@ -289,16 +354,45 @@ class Product < ActiveRecord::Base
289
354
  end
290
355
  ```
291
356
 
357
+ You can specify a scope instead of a where condition string for `column_names`:
358
+
359
+ ```ruby
360
+ class Product < ActiveRecord::Base
361
+ belongs_to :category
362
+ scope :awesomes, ->{ where "products.product_type = ?", 'awesome' }
363
+ scope :suckys, ->{ where "products.product_type = ?", 'sucky' }
364
+
365
+ counter_culture :category,
366
+ column_name: proc {|model| "#{model.product_type}_count" },
367
+ column_names: {
368
+ Product.awesomes => :awesome_count,
369
+ Product.suckys => :sucky_count
370
+ }
371
+ end
372
+ ```
373
+
374
+ If you would like to avoid this configuration and simply skip counter caches with
375
+ dynamic column names, while still fixing those counters on the model that are not
376
+ dynamic, you can pass `skip_unsupported`:
377
+
378
+ ```ruby
379
+ Product.counter_culture_fix_counts skip_unsupported: true
380
+ ```
381
+
292
382
  #### Handling over-written, dynamic foreign keys
293
383
 
294
384
  Manually populating counter caches with dynamically over-written foreign keys (```:foreign_key_values``` option) is not supported. You will have to write code to handle this case yourself.
295
385
 
296
- ### Soft-deletes / `paranoia` gem
386
+ ### Soft-deletes with `paranoia` or `discard`
387
+
388
+ This gem will keep counters correctly updated in Rails 4.2 or later when using
389
+ [paranoia](https://github.com/rubysherpas/paranoia) or
390
+ [discard](https://github.com/jhawthorn/discard) for soft-delete support.
391
+ However, to ensure that counts are incremented after a restore you have
392
+ to make sure to set up soft deletion (via `acts_as_paranoid` or
393
+ `include Discard::Model`) before the call to `counter_culture` in your model:
297
394
 
298
- This gem will keep counters correctly updated when using the `paranoia` gem for
299
- soft-delete support. However, to ensure that counts are incremented after a
300
- restore you have to make sure that the call to `acts_as_paranoid` comes before
301
- the call to `counter_culture` in your model:
395
+ #### Paranoia
302
396
 
303
397
  ```ruby
304
398
  class SoftDelete < ActiveRecord::Base
@@ -309,6 +403,33 @@ class SoftDelete < ActiveRecord::Base
309
403
  end
310
404
  ```
311
405
 
406
+ #### Discard
407
+
408
+ ```ruby
409
+ class SoftDelete < ActiveRecord::Base
410
+ include Discard::Model
411
+
412
+ belongs_to :company
413
+ counter_culture :company
414
+ end
415
+ ```
416
+
417
+ ### PaperTrail integration
418
+
419
+ If you are using the [`paper_trail` gem](https://github.com/airblade/paper_trail)
420
+ and would like new versions to be created when the counter cache columns are
421
+ changed by counter_culture, you can set the `with_papertrail` option:
422
+
423
+ ```ruby
424
+ class Review < ActiveRecord::Base
425
+ counter_culture :product, with_papertrail: true
426
+ end
427
+
428
+ class Product < ActiveRecord::Base
429
+ has_paper_trail
430
+ end
431
+ ```
432
+
312
433
  #### Polymorphic associations
313
434
 
314
435
  counter_culture now supports polymorphic associations of one level only.