counter_culture 2.7.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +17 -6
- data/Appraisals +14 -2
- data/CHANGELOG.md +5 -0
- data/README.md +12 -2
- data/counter_culture.gemspec +2 -1
- data/gemfiles/rails_4.2.gemfile +1 -0
- data/gemfiles/rails_5.0.gemfile +1 -1
- data/gemfiles/rails_5.1.gemfile +1 -1
- data/gemfiles/rails_5.2.gemfile +2 -2
- data/gemfiles/rails_6.0.gemfile +2 -2
- data/gemfiles/rails_6.1.gemfile +10 -0
- data/lib/counter_culture/counter.rb +30 -8
- data/lib/counter_culture/version.rb +1 -1
- data/run_tests_locally.sh +1 -1
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd2787a78c042c84c8585261e4fb2f2975fd5688833de084e6936cb605fd85d6
|
4
|
+
data.tar.gz: dc42bb90b178eca596a17ceb0455ea8cd499d615f66f585a357ed3d6584987fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b015b805b60250331318aa8e0c66b8f313e1b6e9f7da3d8dbee966463b2b7c15adc6be042f572fa0a6fe0df0baf323219eb1aaf2bd2c4df8d4519c929d089bdc
|
7
|
+
data.tar.gz: 00b1cd20630a952f7dd435da9fff6ef9700f3c9dd2e8330a180bb0c4768aede7ca718e7dfbf0a61df5c9c6cd169c43551c6970a8cf70d186a9b4ae940df4e300
|
data/.travis.yml
CHANGED
@@ -1,31 +1,42 @@
|
|
1
1
|
language: ruby
|
2
|
+
cache:
|
3
|
+
directories:
|
4
|
+
- ~/.rvm/gems
|
2
5
|
services:
|
3
6
|
- postgresql
|
4
7
|
- mysql
|
5
8
|
addons:
|
6
9
|
postgresql: "9.6"
|
7
10
|
rvm:
|
8
|
-
- "2.5.
|
9
|
-
- "2.6.
|
10
|
-
- "2.7.
|
11
|
+
- "2.5.8"
|
12
|
+
- "2.6.6"
|
13
|
+
- "2.7.2"
|
14
|
+
- "3.0.0"
|
11
15
|
gemfile:
|
12
16
|
- gemfiles/rails_4.2.gemfile
|
13
17
|
- gemfiles/rails_5.0.gemfile
|
14
18
|
- gemfiles/rails_5.1.gemfile
|
15
19
|
- gemfiles/rails_5.2.gemfile
|
16
20
|
- gemfiles/rails_6.0.gemfile
|
21
|
+
- gemfiles/rails_6.1.gemfile
|
17
22
|
matrix:
|
18
23
|
exclude:
|
19
|
-
- rvm: "
|
24
|
+
- rvm: "3.0.0"
|
20
25
|
gemfile: gemfiles/rails_4.2.gemfile
|
26
|
+
- rvm: "3.0.0"
|
27
|
+
gemfile: gemfiles/rails_5.0.gemfile
|
28
|
+
- rvm: "3.0.0"
|
29
|
+
gemfile: gemfiles/rails_5.1.gemfile
|
30
|
+
- rvm: "3.0.0"
|
31
|
+
gemfile: gemfiles/rails_5.2.gemfile
|
21
32
|
env:
|
22
33
|
- DB=postgresql
|
23
34
|
- DB=sqlite3
|
24
35
|
- DB=mysql2
|
25
36
|
before_install:
|
26
|
-
- gem install bundler -v '1.17.3'
|
37
|
+
- if [ "$BUNDLE_GEMFILE" = "$PWD/gemfiles/rails_4.2.gemfile" ]; then gem install bundler -v '1.17.3'; else gem install bundler -v '> 2'; fi
|
27
38
|
install:
|
28
|
-
- bundle _1.17.3_ update
|
39
|
+
- if [ "$BUNDLE_GEMFILE" = "$PWD/gemfiles/rails_4.2.gemfile" ]; then bundle _1.17.3_ update; else bundle update; fi
|
29
40
|
before_script:
|
30
41
|
- psql -c 'create database counter_culture_test;' -U postgres
|
31
42
|
- mysql -e 'CREATE DATABASE counter_culture_test;'
|
data/Appraisals
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
5.1
|
5
5
|
5.2
|
6
6
|
6.0
|
7
|
+
6.1
|
7
8
|
].each do |rails_version|
|
8
9
|
gem_rails_version = Gem::Version.new(rails_version)
|
9
10
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0') &&
|
@@ -15,8 +16,19 @@
|
|
15
16
|
appraise "rails-#{rails_version}" do
|
16
17
|
gem 'rails', "~> #{rails_version}.0"
|
17
18
|
|
18
|
-
|
19
|
+
if gem_rails_version < Gem::Version.new('5.0')
|
20
|
+
gem 'pg', '~> 0.15'
|
21
|
+
else
|
22
|
+
gem 'pg'
|
23
|
+
end
|
19
24
|
gem 'mysql2'
|
20
|
-
|
25
|
+
if gem_rails_version < Gem::Version.new('5.2')
|
26
|
+
gem 'sqlite3', '~> 1.3.0'
|
27
|
+
else
|
28
|
+
gem 'sqlite3'
|
29
|
+
end
|
30
|
+
if gem_rails_version < Gem::Version.new('5.0')
|
31
|
+
gem 'bigdecimal', '~> 1.3.5'
|
32
|
+
end
|
21
33
|
end
|
22
34
|
end
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,7 @@ 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.
|
10
|
+
Tested against Ruby 2.5.8, 2.6.6, 2.7.2 and 3.0.0, and against the latest patch releases of Rails 4.2, 5.0, 5.1, 5.2, 6.0 and 6.1.
|
11
11
|
|
12
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
13
|
```
|
@@ -250,6 +250,16 @@ You may also specify a custom timestamp column that gets updated only when a par
|
|
250
250
|
|
251
251
|
With this option, any time the `category_counter_cache` changes both the `category_count_changed` and `updated_at` columns will get updated.
|
252
252
|
|
253
|
+
### Avoiding deadlocks / executing counter cache updates after commit
|
254
|
+
|
255
|
+
Some applications run into issues with deadlocks involving counter cache updates when using this gem. See [#263](https://github.com/magnusvk/counter_culture/issues/263#issuecomment-772284439) for information and helpful links on how to avoid this issue.
|
256
|
+
|
257
|
+
Another option is to simply defer the update of counter caches to outside of the transaction. This gives up transacrtional guarantees for your counter cache updates but should resolve any deadlocks you experience. This behavior is disabled by default, enable it on each affected counter cache as follows:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
counter_culture :category, execute_after_commit: true
|
261
|
+
```
|
262
|
+
|
253
263
|
### Manually populating counter cache values
|
254
264
|
|
255
265
|
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.
|
@@ -446,4 +456,4 @@ counter_culture now supports polymorphic associations of one level only.
|
|
446
456
|
|
447
457
|
## Copyright
|
448
458
|
|
449
|
-
Copyright (c) 2012-
|
459
|
+
Copyright (c) 2012-2021 BestVendor, Magnus von Koeller. See LICENSE.txt for further details.
|
data/counter_culture.gemspec
CHANGED
@@ -30,11 +30,12 @@ Gem::Specification.new do |spec|
|
|
30
30
|
|
31
31
|
spec.add_development_dependency 'appraisal', '> 2.0.0'
|
32
32
|
spec.add_development_dependency 'awesome_print'
|
33
|
-
spec.add_development_dependency 'bundler'
|
33
|
+
spec.add_development_dependency 'bundler'
|
34
34
|
spec.add_development_dependency 'database_cleaner', '>= 1.1.1'
|
35
35
|
spec.add_development_dependency 'discard'
|
36
36
|
spec.add_development_dependency 'paper_trail'
|
37
37
|
spec.add_development_dependency 'paranoia'
|
38
|
+
spec.add_development_dependency 'after_commit_action'
|
38
39
|
spec.add_development_dependency 'rails', '>= 4.2'
|
39
40
|
spec.add_development_dependency 'rake', '>= 10.0'
|
40
41
|
spec.add_development_dependency 'rdoc', '~> 5.0.0'
|
data/gemfiles/rails_4.2.gemfile
CHANGED
data/gemfiles/rails_5.0.gemfile
CHANGED
data/gemfiles/rails_5.1.gemfile
CHANGED
data/gemfiles/rails_5.2.gemfile
CHANGED
data/gemfiles/rails_6.0.gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module CounterCulture
|
2
2
|
class Counter
|
3
|
-
CONFIG_OPTIONS = [ :column_names, :counter_cache_name, :delta_column, :foreign_key_values, :touch, :delta_magnitude]
|
3
|
+
CONFIG_OPTIONS = [ :column_names, :counter_cache_name, :delta_column, :foreign_key_values, :touch, :delta_magnitude, :execute_after_commit ]
|
4
4
|
ACTIVE_RECORD_VERSION = Gem.loaded_specs["activerecord"].version
|
5
5
|
|
6
6
|
attr_reader :model, :relation, *CONFIG_OPTIONS
|
@@ -9,10 +9,6 @@ module CounterCulture
|
|
9
9
|
@model = model
|
10
10
|
@relation = relation.is_a?(Enumerable) ? relation : [relation]
|
11
11
|
|
12
|
-
if options.fetch(:execute_after_commit, false)
|
13
|
-
fail("execute_after_commit was removed; updates now run within the transaction")
|
14
|
-
end
|
15
|
-
|
16
12
|
@counter_cache_name = options.fetch(:column_name, "#{model.name.demodulize.tableize}_count")
|
17
13
|
@column_names = options[:column_names]
|
18
14
|
@delta_column = options[:delta_column]
|
@@ -20,6 +16,18 @@ module CounterCulture
|
|
20
16
|
@touch = options.fetch(:touch, false)
|
21
17
|
@delta_magnitude = options[:delta_magnitude] || 1
|
22
18
|
@with_papertrail = options.fetch(:with_papertrail, false)
|
19
|
+
@execute_after_commit = options.fetch(:execute_after_commit, false)
|
20
|
+
|
21
|
+
if @execute_after_commit
|
22
|
+
begin
|
23
|
+
require 'after_commit_action'
|
24
|
+
rescue LoadError
|
25
|
+
fail(LoadError.new(
|
26
|
+
"You need to include the `after_commit_action` gem in your "\
|
27
|
+
"gem dependencies to use the execute_after_commit option"))
|
28
|
+
end
|
29
|
+
model.include(AfterCommitAction)
|
30
|
+
end
|
23
31
|
end
|
24
32
|
|
25
33
|
# increments or decrements a counter cache
|
@@ -93,14 +101,20 @@ module CounterCulture
|
|
93
101
|
instance.send("#{timestamp_column}=", current_time)
|
94
102
|
end
|
95
103
|
|
96
|
-
|
104
|
+
execute_now_or_after_commit(obj) do
|
105
|
+
instance.paper_trail.save_with_version(validate: false)
|
106
|
+
end
|
97
107
|
else
|
98
|
-
|
108
|
+
execute_now_or_after_commit(obj) do
|
109
|
+
instance.paper_trail.touch_with_version
|
110
|
+
end
|
99
111
|
end
|
100
112
|
end
|
101
113
|
end
|
102
114
|
|
103
|
-
|
115
|
+
execute_now_or_after_commit(obj) do
|
116
|
+
klass.where(primary_key => id_to_change).update_all updates.join(', ')
|
117
|
+
end
|
104
118
|
end
|
105
119
|
end
|
106
120
|
|
@@ -296,6 +310,14 @@ module CounterCulture
|
|
296
310
|
prev
|
297
311
|
end
|
298
312
|
|
313
|
+
def execute_now_or_after_commit(obj, &block)
|
314
|
+
if @execute_after_commit
|
315
|
+
obj.execute_after_commit(&block)
|
316
|
+
else
|
317
|
+
block.call
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
299
321
|
private
|
300
322
|
def attribute_was(obj, attr)
|
301
323
|
changes_method =
|
data/run_tests_locally.sh
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: counter_culture
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Magnus von Koeller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: database_cleaner
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: after_commit_action
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: rails
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -263,6 +277,7 @@ files:
|
|
263
277
|
- gemfiles/rails_5.1.gemfile
|
264
278
|
- gemfiles/rails_5.2.gemfile
|
265
279
|
- gemfiles/rails_6.0.gemfile
|
280
|
+
- gemfiles/rails_6.1.gemfile
|
266
281
|
- lib/counter_culture.rb
|
267
282
|
- lib/counter_culture/counter.rb
|
268
283
|
- lib/counter_culture/extensions.rb
|