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
data/Rakefile CHANGED
@@ -1,48 +1,21 @@
1
- # encoding: utf-8
2
-
3
1
  require 'rubygems'
4
2
  require 'bundler'
5
- begin
6
- Bundler.setup(:default, :development)
7
- rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
10
- exit e.status_code
11
- end
12
- require 'rake'
13
-
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
16
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
- gem.name = "counter_culture"
18
- gem.homepage = "http://github.com/magnusvk/counter_culture"
19
- gem.license = "MIT"
20
- gem.summary = %Q{Turbo-charged counter caches for your Rails app.}
21
- gem.description = %Q{counter_culture provides turbo-charged counter caches that are kept up-to-date not just on create and destroy, that support multiple levels of indirection through relationships, allow dynamic column names and that avoid deadlocks by updating in the after_commit callback.}
22
- gem.email = "magnus@vonkoeller.de"
23
- gem.authors = ["Magnus von Koeller"]
24
- end
25
- Jeweler::RubygemsDotOrgTasks.new
26
-
27
- require 'rspec/core'
3
+ require 'bundler/gem_tasks'
28
4
  require 'rspec/core/rake_task'
5
+ require 'rdoc/task'
6
+ require 'counter_culture/version'
7
+
29
8
  RSpec::Core::RakeTask.new(:spec) do |spec|
30
9
  spec.pattern = FileList['spec/**/*_spec.rb']
31
10
  end
32
11
 
33
- RSpec::Core::RakeTask.new(:rcov) do |spec|
34
- spec.pattern = 'spec/**/*_spec.rb'
35
- spec.rcov = true
36
- end
37
-
38
- task :default => :spec
39
-
40
- require 'rdoc/task'
41
12
  Rake::RDocTask.new do |rdoc|
42
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
13
+ version = CounterCulture::VERSION
43
14
 
44
15
  rdoc.rdoc_dir = 'rdoc'
45
16
  rdoc.title = "counter_culture #{version}"
46
17
  rdoc.rdoc_files.include('README*')
47
18
  rdoc.rdoc_files.include('lib/**/*.rb')
48
19
  end
20
+
21
+ task default: :spec
@@ -1,174 +1,45 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: counter_culture 1.8.0 ruby lib
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'counter_culture/version'
6
4
 
7
- Gem::Specification.new do |s|
8
- s.name = "counter_culture"
9
- s.version = "1.8.0"
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'counter_culture'
7
+ spec.version = CounterCulture::VERSION
8
+ spec.authors = ['Magnus von Koeller']
9
+ spec.email = ["magnus@vonkoeller.de"]
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["Magnus von Koeller"]
14
- s.date = "2017-08-30"
15
- s.description = "counter_culture provides turbo-charged counter caches that are kept up-to-date not just on create and destroy, that support multiple levels of indirection through relationships, allow dynamic column names and that avoid deadlocks by updating in the after_commit callback."
16
- s.email = "magnus@vonkoeller.de"
17
- s.extra_rdoc_files = [
18
- "LICENSE.txt",
19
- "README.md"
20
- ]
21
- s.files = [
22
- ".document",
23
- ".rspec",
24
- ".travis.yml",
25
- "CHANGELOG.md",
26
- "Gemfile",
27
- "LICENSE.txt",
28
- "README.md",
29
- "Rakefile",
30
- "VERSION",
31
- "circle.yml",
32
- "counter_culture.gemspec",
33
- "lib/counter_culture.rb",
34
- "lib/counter_culture/counter.rb",
35
- "lib/counter_culture/extensions.rb",
36
- "lib/counter_culture/reconciler.rb",
37
- "lib/generators/counter_culture_generator.rb",
38
- "lib/generators/templates/counter_culture_migration.rb.erb",
39
- "spec/counter_culture_spec.rb",
40
- "spec/models/another_post.rb",
41
- "spec/models/another_post_comment.rb",
42
- "spec/models/candidate.rb",
43
- "spec/models/candidate_profile.rb",
44
- "spec/models/categ.rb",
45
- "spec/models/category.rb",
46
- "spec/models/company.rb",
47
- "spec/models/conditional_dependent.rb",
48
- "spec/models/conditional_main.rb",
49
- "spec/models/conversation.rb",
50
- "spec/models/has_string_id.rb",
51
- "spec/models/industry.rb",
52
- "spec/models/person.rb",
53
- "spec/models/poly_employee.rb",
54
- "spec/models/poly_image.rb",
55
- "spec/models/poly_product.rb",
56
- "spec/models/post.rb",
57
- "spec/models/post_comment.rb",
58
- "spec/models/product.rb",
59
- "spec/models/review.rb",
60
- "spec/models/simple_dependent.rb",
61
- "spec/models/simple_main.rb",
62
- "spec/models/simple_review.rb",
63
- "spec/models/soft_delete.rb",
64
- "spec/models/subcateg.rb",
65
- "spec/models/transaction.rb",
66
- "spec/models/twitter_review.rb",
67
- "spec/models/user.rb",
68
- "spec/rails_app/.gitignore",
69
- "spec/rails_app/Gemfile",
70
- "spec/rails_app/Gemfile.lock",
71
- "spec/rails_app/README.rdoc",
72
- "spec/rails_app/Rakefile",
73
- "spec/rails_app/app/assets/images/rails.png",
74
- "spec/rails_app/app/assets/javascripts/application.js",
75
- "spec/rails_app/app/assets/stylesheets/application.css",
76
- "spec/rails_app/app/controllers/application_controller.rb",
77
- "spec/rails_app/app/helpers/application_helper.rb",
78
- "spec/rails_app/app/mailers/.gitkeep",
79
- "spec/rails_app/app/models/.gitkeep",
80
- "spec/rails_app/app/views/layouts/application.html.erb",
81
- "spec/rails_app/config.ru",
82
- "spec/rails_app/config/application.rb",
83
- "spec/rails_app/config/boot.rb",
84
- "spec/rails_app/config/database.yml",
85
- "spec/rails_app/config/environment.rb",
86
- "spec/rails_app/config/environments/development.rb",
87
- "spec/rails_app/config/environments/test.rb",
88
- "spec/rails_app/config/initializers/backtrace_silencers.rb",
89
- "spec/rails_app/config/initializers/inflections.rb",
90
- "spec/rails_app/config/initializers/mime_types.rb",
91
- "spec/rails_app/config/initializers/paper_trail.rb",
92
- "spec/rails_app/config/initializers/secret_token.rb",
93
- "spec/rails_app/config/initializers/session_store.rb",
94
- "spec/rails_app/config/initializers/wrap_parameters.rb",
95
- "spec/rails_app/config/locales/en.yml",
96
- "spec/rails_app/config/routes.rb",
97
- "spec/rails_app/db/seeds.rb",
98
- "spec/rails_app/lib/assets/.gitkeep",
99
- "spec/rails_app/lib/tasks/.gitkeep",
100
- "spec/rails_app/log/.gitkeep",
101
- "spec/rails_app/public/404.html",
102
- "spec/rails_app/public/422.html",
103
- "spec/rails_app/public/500.html",
104
- "spec/rails_app/public/favicon.ico",
105
- "spec/rails_app/public/index.html",
106
- "spec/rails_app/public/robots.txt",
107
- "spec/rails_app/script/rails",
108
- "spec/rails_app/test/fixtures/.gitkeep",
109
- "spec/rails_app/test/functional/.gitkeep",
110
- "spec/rails_app/test/integration/.gitkeep",
111
- "spec/rails_app/test/performance/browsing_test.rb",
112
- "spec/rails_app/test/test_helper.rb",
113
- "spec/rails_app/test/unit/.gitkeep",
114
- "spec/rails_app/vendor/assets/javascripts/.gitkeep",
115
- "spec/rails_app/vendor/assets/stylesheets/.gitkeep",
116
- "spec/rails_app/vendor/plugins/.gitkeep",
117
- "spec/schema.rb",
118
- "spec/spec_helper.rb",
119
- "test_rails_versions.sh"
120
- ]
121
- s.homepage = "http://github.com/magnusvk/counter_culture"
122
- s.licenses = ["MIT"]
123
- s.rubygems_version = "2.5.1"
124
- s.summary = "Turbo-charged counter caches for your Rails app."
11
+ spec.summary = 'Turbo-charged counter caches for your Rails app.'
12
+ spec.description = 'counter_culture provides turbo-charged counter caches that are kept up-to-date not just on create and destroy, that support multiple levels of indirection through relationships, allow dynamic column names and that avoid deadlocks by updating in the after_commit callback.'
13
+ spec.homepage = 'https://github.com/magnusvk/counter_culture'
14
+ spec.license = 'MIT'
125
15
 
126
- if s.respond_to? :specification_version then
127
- s.specification_version = 4
16
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
128
17
 
129
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
130
- s.add_runtime_dependency(%q<after_commit_action>, ["~> 1.0"])
131
- s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0"])
132
- s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0"])
133
- s.add_development_dependency(%q<rake>, [">= 0"])
134
- s.add_development_dependency(%q<rails>, [">= 3.1.0"])
135
- s.add_development_dependency(%q<rspec>, ["~> 3.0"])
136
- s.add_development_dependency(%q<awesome_print>, [">= 0"])
137
- s.add_development_dependency(%q<timecop>, [">= 0"])
138
- s.add_development_dependency(%q<paranoia>, [">= 0"])
139
- s.add_development_dependency(%q<paper_trail>, [">= 0"])
140
- s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
141
- s.add_development_dependency(%q<bundler>, [">= 1.2.0"])
142
- s.add_development_dependency(%q<jeweler>, ["~> 2.1"])
143
- else
144
- s.add_dependency(%q<after_commit_action>, ["~> 1.0"])
145
- s.add_dependency(%q<activerecord>, [">= 3.0.0"])
146
- s.add_dependency(%q<activesupport>, [">= 3.0.0"])
147
- s.add_dependency(%q<rake>, [">= 0"])
148
- s.add_dependency(%q<rails>, [">= 3.1.0"])
149
- s.add_dependency(%q<rspec>, ["~> 3.0"])
150
- s.add_dependency(%q<awesome_print>, [">= 0"])
151
- s.add_dependency(%q<timecop>, [">= 0"])
152
- s.add_dependency(%q<paranoia>, [">= 0"])
153
- s.add_dependency(%q<paper_trail>, [">= 0"])
154
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
155
- s.add_dependency(%q<bundler>, [">= 1.2.0"])
156
- s.add_dependency(%q<jeweler>, ["~> 2.1"])
157
- end
158
- else
159
- s.add_dependency(%q<after_commit_action>, ["~> 1.0"])
160
- s.add_dependency(%q<activerecord>, [">= 3.0.0"])
161
- s.add_dependency(%q<activesupport>, [">= 3.0.0"])
162
- s.add_dependency(%q<rake>, [">= 0"])
163
- s.add_dependency(%q<rails>, [">= 3.1.0"])
164
- s.add_dependency(%q<rspec>, ["~> 3.0"])
165
- s.add_dependency(%q<awesome_print>, [">= 0"])
166
- s.add_dependency(%q<timecop>, [">= 0"])
167
- s.add_dependency(%q<paranoia>, [">= 0"])
168
- s.add_dependency(%q<paper_trail>, [">= 0"])
169
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
170
- s.add_dependency(%q<bundler>, [">= 1.2.0"])
171
- s.add_dependency(%q<jeweler>, ["~> 2.1"])
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
172
22
  end
173
- end
23
+ spec.extra_rdoc_files = ['LICENSE.txt', 'README.md']
24
+ spec.bindir = 'exe'
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_dependency 'activerecord', '>= 4.2'
29
+ spec.add_dependency 'activesupport', '>= 4.2'
174
30
 
31
+ spec.add_development_dependency 'appraisal', '> 2.0.0'
32
+ spec.add_development_dependency 'awesome_print'
33
+ spec.add_development_dependency 'bundler', '~> 1.17'
34
+ spec.add_development_dependency 'database_cleaner', '>= 1.1.1'
35
+ spec.add_development_dependency 'discard'
36
+ spec.add_development_dependency 'paper_trail'
37
+ spec.add_development_dependency 'paranoia'
38
+ spec.add_development_dependency 'rails', '>= 4.2'
39
+ spec.add_development_dependency 'rake', '>= 10.0'
40
+ spec.add_development_dependency 'rdoc', '~> 5.0.0'
41
+ spec.add_development_dependency 'rspec', '~> 3.0'
42
+ spec.add_development_dependency 'rspec-extra-formatters'
43
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
44
+ spec.add_development_dependency 'timecop'
45
+ end
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.0"
6
+ gem "rails", "~> 4.2.0"
7
+ gem "pg", "~> 0.15"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.0"
6
+ gem "rails", "~> 5.0.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.3.0"
6
+ gem "rails", "~> 5.1.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.4"
6
+ gem "rails", "~> 5.2.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "sqlite3", "~> 1.4"
6
+ gem "rails", "~> 6.0.0"
7
+ gem "pg", "~> 1.0"
8
+ gem "mysql2"
9
+
10
+ gemspec path: "../"
@@ -1,7 +1,7 @@
1
- require 'after_commit_action'
2
1
  require 'active_support/concern'
3
2
  require 'active_support/lazy_load_hooks'
4
3
 
4
+ require 'counter_culture/version'
5
5
  require 'counter_culture/extensions'
6
6
  require 'counter_culture/counter'
7
7
  require 'counter_culture/reconciler'
@@ -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, :execute_after_commit ]
3
+ CONFIG_OPTIONS = [ :column_names, :counter_cache_name, :delta_column, :foreign_key_values, :touch, :delta_magnitude]
4
4
  ACTIVE_RECORD_VERSION = Gem.loaded_specs["activerecord"].version
5
5
 
6
6
  attr_reader :model, :relation, *CONFIG_OPTIONS
@@ -9,13 +9,16 @@ module CounterCulture
9
9
  @model = model
10
10
  @relation = relation.is_a?(Enumerable) ? relation : [relation]
11
11
 
12
- @counter_cache_name = options.fetch(:column_name, "#{model.name.tableize}_count")
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
+ @counter_cache_name = options.fetch(:column_name, "#{model.name.demodulize.tableize}_count")
13
17
  @column_names = options[:column_names]
14
18
  @delta_column = options[:delta_column]
15
19
  @foreign_key_values = options[:foreign_key_values]
16
20
  @touch = options.fetch(:touch, false)
17
21
  @delta_magnitude = options[:delta_magnitude] || 1
18
- @execute_after_commit = options.fetch(:execute_after_commit, false)
19
22
  @with_papertrail = options.fetch(:with_papertrail, false)
20
23
  end
21
24
 
@@ -29,7 +32,6 @@ module CounterCulture
29
32
  # :delta_column => override the default count delta (1) with the value of this column in the counted record
30
33
  # :was => whether to get the current value or the old value of the
31
34
  # first part of the relation
32
- # :execute_after_commit => execute the column update outside of the transaction to avoid deadlocks
33
35
  # :with_papertrail => update the column via Papertrail touch_with_version method
34
36
  def change_counter_cache(obj, options)
35
37
  change_counter_column = options.fetch(:counter_column) { counter_cache_name_for(obj) }
@@ -45,36 +47,60 @@ module CounterCulture
45
47
  else
46
48
  counter_delta_magnitude_for(obj)
47
49
  end
48
- execute_change_counter_cache(obj, options) do
49
- # increment or decrement?
50
- operator = options[:increment] ? '+' : '-'
51
-
52
- # we don't use Rails' update_counters because we support changing the timestamp
53
- quoted_column = model.connection.quote_column_name(change_counter_column)
54
-
55
- updates = []
56
- # this updates the actual counter
57
- updates << "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{delta_magnitude}"
58
- # and here we update the timestamp, if so desired
59
- if touch
60
- current_time = obj.send(:current_time_from_proper_timezone)
61
- timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
62
- timestamp_columns << touch if touch != true
63
- timestamp_columns.each do |timestamp_column|
64
- updates << "#{timestamp_column} = '#{current_time.to_formatted_s(:db)}'"
65
- end
50
+ # increment or decrement?
51
+ operator = options[:increment] ? '+' : '-'
52
+
53
+ klass = relation_klass(relation, source: obj, was: options[:was])
54
+
55
+ # MySQL throws an ambiguous column error if any joins are present and we don't include the
56
+ # table name. We isolate this change to MySQL because sqlite has the opposite behavior and
57
+ # throws an exception if the table name is present after UPDATE.
58
+ quoted_column = if klass.connection.adapter_name == 'Mysql2'
59
+ "#{klass.quoted_table_name}.#{model.connection.quote_column_name(change_counter_column)}"
60
+ else
61
+ "#{model.connection.quote_column_name(change_counter_column)}"
62
+ end
63
+
64
+ # we don't use Rails' update_counters because we support changing the timestamp
65
+ updates = []
66
+ # this updates the actual counter
67
+ updates << "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{delta_magnitude}"
68
+ # and here we update the timestamp, if so desired
69
+ if touch
70
+ current_time = obj.send(:current_time_from_proper_timezone)
71
+ timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
72
+ if touch != true
73
+ # starting in Rails 6 this is frozen
74
+ timestamp_columns = timestamp_columns.dup
75
+ timestamp_columns << touch
76
+ end
77
+ timestamp_columns.each do |timestamp_column|
78
+ updates << "#{timestamp_column} = '#{current_time.to_formatted_s(:db)}'"
66
79
  end
80
+ end
67
81
 
68
- klass = relation_klass(relation, source: obj, was: options[:was])
69
- primary_key = relation_primary_key(relation, source: obj, was: options[:was])
82
+ primary_key = relation_primary_key(relation, source: obj, was: options[:was])
70
83
 
71
- if @with_papertrail
72
- instance = klass.where(primary_key => id_to_change).first
73
- instance.paper_trail.touch_with_version if instance
74
- end
84
+ if @with_papertrail
85
+ instance = klass.where(primary_key => id_to_change).first
86
+ if instance
87
+ if instance.paper_trail.respond_to?(:save_with_version)
88
+ # touch_with_version is deprecated starting in PaperTrail 9.0.0
89
+
90
+ current_time = obj.send(:current_time_from_proper_timezone)
91
+ timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
92
+ timestamp_columns.each do |timestamp_column|
93
+ instance.send("#{timestamp_column}=", current_time)
94
+ end
75
95
 
76
- klass.where(primary_key => id_to_change).update_all updates.join(', ')
96
+ instance.paper_trail.save_with_version(validate: false)
97
+ else
98
+ instance.paper_trail.touch_with_version
99
+ end
100
+ end
77
101
  end
102
+
103
+ klass.where(primary_key => id_to_change).update_all updates.join(', ')
78
104
  end
79
105
  end
80
106
 
@@ -264,21 +290,13 @@ module CounterCulture
264
290
  changes_method = ACTIVE_RECORD_VERSION >= Gem::Version.new("5.1.0") ? :saved_changes : :changed_attributes
265
291
  obj.public_send(changes_method).each do |key, value|
266
292
  old_value = ACTIVE_RECORD_VERSION >= Gem::Version.new("5.1.0") ? value.first : value
267
- prev.public_send("#{key}=", old_value)
293
+ prev[key] = old_value
268
294
  end
269
295
 
270
296
  prev
271
297
  end
272
298
 
273
299
  private
274
- def execute_change_counter_cache(obj, options)
275
- if execute_after_commit
276
- obj.execute_after_commit { yield }
277
- else
278
- yield
279
- end
280
- end
281
-
282
300
  def attribute_was(obj, attr)
283
301
  changes_method =
284
302
  if ACTIVE_RECORD_VERSION >= Gem::Version.new("5.1.0")