awesome_counter_cache 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a438135d0099fbe7652b5f754180b2f396650129a62066e364dee2fd69666bc4
4
- data.tar.gz: 27ce6f7009265b2a1022793a1ff43af3e57a9f9dd6340d660299dbe1afbc78a1
3
+ metadata.gz: da9f3b10f0b3d3f91d23585c3cbb6234b585987d7d4ba4704026de6871830e66
4
+ data.tar.gz: '09a7a1388a4d93709e10712d8dd3d8a9c7ad0af76a456d4b2b2b674a1f697d6b'
5
5
  SHA512:
6
- metadata.gz: 1420eddc1824fc764e9f2a62a8d6464860366b945bd8112ef94d28082fd718cb6fecc617d32b7c50a67a9c0f5f79e593d007e1c2f3ec4e5609b34388cca3e6a7
7
- data.tar.gz: ef5c2e47f810091cb35a302f1a738bbdf93336efb6a72969fc6116f0cdfc361cb4c103d13f6cfcc6f8ba809433c22243485246cd8b82be44347fd604a904de82
6
+ metadata.gz: 635c8b6ba277428198ab978addf81aa9723b713d26f4dcf6a6a26bdc84ef84a444c7450be3cb4b1419afbb699be7f60fbaafcca92a7c8bb328f5d794cfcd274b
7
+ data.tar.gz: ccd61848475acd36066de42204772e0ea8d0778e4a4ebda7b7dc26f3fe1de0f13cdc4f91d083e63a770a2df61328b2ddfe15cc15049a04e805f20fa1d703ba8e
data/README.md CHANGED
@@ -1,3 +1,9 @@
1
1
  # AwesomeCounterCache
2
2
 
3
- This project rocks and uses MIT-LICENSE.
3
+ This project rocks and uses MIT-LICENSE.
4
+
5
+ ## Testing
6
+
7
+ ```bash
8
+ DATABASE_URL=sqlite3://db/home/build/project/spec/dummy/db/test.sqlite3 bundle exec rspec
9
+ ```
@@ -1,28 +1,32 @@
1
1
  module AwesomeCounterCache::ClassMethods
2
2
  def awesome_counter_cache_for(relation_name, args = {})
3
3
  id = awesome_counter_caches.length
4
-
5
4
  args[:column_name] ||= "#{model_name.plural}_count"
6
5
  args[:delta_magnitude] ||= proc { 1 }
6
+ args[:relation_foreign_key] = reflections.fetch(relation_name.to_s).foreign_key
7
7
  args[:relation_name] = relation_name
8
8
  args[:id] = id
9
9
 
10
- awesome_counter_caches[id] = args
10
+ counter_cache = AwesomeCounterCache::CounterCache.new(**args)
11
+ awesome_counter_caches[id] = counter_cache
12
+ awesome_counter_cache_init_callbacks(counter_cache)
13
+ end
11
14
 
15
+ def awesome_counter_cache_init_callbacks(counter_cache)
12
16
  after_initialize do |model|
13
- awesome_counter_cache_after_initialize(args, model)
17
+ awesome_counter_cache_after_initialize(counter_cache, model)
14
18
  end
15
19
 
16
20
  after_commit on: :create do |model|
17
- awesome_counter_cache_after_commit_on_create(args, model, relation_name)
21
+ awesome_counter_cache_after_commit_on_create(counter_cache, model)
18
22
  end
19
23
 
20
24
  after_commit on: :destroy do |model|
21
- awesome_counter_cache_after_commit_on_destroy(args, model, relation_name)
25
+ awesome_counter_cache_after_commit_on_destroy(counter_cache, model)
22
26
  end
23
27
 
24
28
  after_commit on: :update do |model|
25
- awesome_counter_cache_after_commit_on_update(args, model, relation_name)
29
+ awesome_counter_cache_after_commit_on_update(counter_cache, model)
26
30
  end
27
31
  end
28
32
 
@@ -0,0 +1,11 @@
1
+ class AwesomeCounterCache::CounterCache
2
+ attr_accessor :column_name, :delta_magnitude, :id, :relation_foreign_key, :relation_name
3
+
4
+ def initialize(column_name:, delta_magnitude:, id:, relation_foreign_key:, relation_name:)
5
+ @column_name = column_name
6
+ @delta_magnitude = delta_magnitude
7
+ @id = id
8
+ @relation_foreign_key = relation_foreign_key
9
+ @relation_name = relation_name
10
+ end
11
+ end
@@ -1,49 +1,55 @@
1
1
  module AwesomeCounterCache::InstanceMethods
2
- def awesome_counter_cache_after_commit_on_create(args, model, relation_name)
3
- id = args.fetch(:id)
4
- @awesome_counter_cache_data.fetch(id)[:delta_current] = args.fetch(:delta_magnitude).call(model)
5
- model.create_awesome_counter_cache_for(relation_name, @awesome_counter_cache_data.fetch(id), args)
6
- @awesome_counter_cache_data[id][:delta_original] = @awesome_counter_cache_data[id].delete(:delta_current)
2
+ def awesome_counter_cache_after_commit_on_create(counter_cache, model)
3
+ id = counter_cache.id
4
+ state = @awesome_counter_cache_data.fetch(id)
5
+ state.delta_current = counter_cache.delta_magnitude.call(model)
6
+ model.create_awesome_counter_cache_for(counter_cache.relation_name, @awesome_counter_cache_data.fetch(id), counter_cache)
7
+ state.delta_original = state.delta_current
8
+ state.delta_current = nil
7
9
  end
8
10
 
9
- def awesome_counter_cache_after_commit_on_destroy(args, model, relation_name)
10
- id = args.fetch(:id)
11
- @awesome_counter_cache_data.fetch(id)[:delta_current] = args.fetch(:delta_magnitude).call(model)
12
- model.destroy_awesome_counter_cache_for(relation_name, @awesome_counter_cache_data.fetch(id), args)
13
- @awesome_counter_cache_data[id][:delta_original] = @awesome_counter_cache_data[id].delete(:delta_current)
11
+ def awesome_counter_cache_after_commit_on_destroy(counter_cache, model)
12
+ id = counter_cache.id
13
+ state = @awesome_counter_cache_data.fetch(id)
14
+ state.delta_current = counter_cache.delta_magnitude.call(model)
15
+ model.destroy_awesome_counter_cache_for(counter_cache.relation_name, @awesome_counter_cache_data.fetch(id), counter_cache)
16
+ state.delta_original = state.delta_current
17
+ state.delta_current = nil
14
18
  end
15
19
 
16
- def awesome_counter_cache_after_commit_on_update(args, model, relation_name)
17
- id = args.fetch(:id)
18
- @awesome_counter_cache_data.fetch(id)[:delta_current] = args.fetch(:delta_magnitude).call(model)
19
- model.update_awesome_counter_cache_for(relation_name, @awesome_counter_cache_data.fetch(id), args)
20
- @awesome_counter_cache_data[id][:delta_original] = @awesome_counter_cache_data[id].delete(:delta_current)
20
+ def awesome_counter_cache_after_commit_on_update(counter_cache, model)
21
+ id = counter_cache.id
22
+ state = @awesome_counter_cache_data.fetch(id)
23
+ state.delta_current = counter_cache.delta_magnitude.call(model)
24
+ model.update_awesome_counter_cache_for(counter_cache.relation_name, @awesome_counter_cache_data.fetch(id), counter_cache)
25
+ state.delta_original = state.delta_current
26
+ state.delta_current = nil
21
27
  end
22
28
 
23
- def awesome_counter_cache_after_initialize(args, model)
24
- id = args.fetch(:id)
29
+ def awesome_counter_cache_after_initialize(counter_cache, model)
30
+ id = counter_cache.id
25
31
 
26
32
  @awesome_counter_cache_data ||= {}
27
- @awesome_counter_cache_data[id] ||= {}
33
+ @awesome_counter_cache_data[id] ||= AwesomeCounterCache::State.new
28
34
 
29
35
  primary_key_column = self.class.primary_key
30
36
 
31
37
  if read_attribute(primary_key_column).nil? # `new_record?` always returns false so check if primary key is nil instead - kaspernj
32
- @awesome_counter_cache_data.fetch(id)[:delta_original] ||= 0
38
+ @awesome_counter_cache_data.fetch(id).delta_original ||= 0
33
39
  else
34
- @awesome_counter_cache_data.fetch(id)[:delta_original] ||= args.fetch(:delta_magnitude).call(model)
40
+ @awesome_counter_cache_data.fetch(id).delta_original ||= counter_cache.delta_magnitude.call(model)
35
41
  end
36
42
  end
37
43
 
38
- def create_awesome_counter_cache_for(relation_name, state_data, args)
44
+ def create_awesome_counter_cache_for(relation_name, state, counter_cache)
39
45
  relation_model = __send__(relation_name)
40
46
  return if relation_model.blank?
41
47
 
42
- addition = state_data.fetch(:delta_current)
48
+ addition = state.delta_current
43
49
 
44
50
  if addition != 0
45
51
  primary_key_value = relation_model.read_attribute(relation_model.class.primary_key)
46
- relation_model.class.update_counters(primary_key_value, args.fetch(:column_name) => addition)
52
+ relation_model.class.update_counters(primary_key_value, counter_cache.column_name => addition) # rubocop:disable Rails/SkipsModelValidations
47
53
  end
48
54
  end
49
55
 
@@ -54,32 +60,45 @@ module AwesomeCounterCache::InstanceMethods
54
60
  end
55
61
 
56
62
  def awesome_counter_cache_reset_original_values
57
- self.class.awesome_counter_caches.each do |id, args|
58
- @awesome_counter_cache_data.fetch(id)[:delta_original] = args.fetch(:delta_magnitude).call(self)
63
+ self.class.awesome_counter_caches.each do |id, counter_cache|
64
+ state = @awesome_counter_cache_data.fetch(id)
65
+ state.delta_original = counter_cache.delta_magnitude.call(self)
59
66
  end
60
67
  end
61
68
 
62
- def destroy_awesome_counter_cache_for(relation_name, state_data, args)
69
+ def destroy_awesome_counter_cache_for(relation_name, state, counter_cache)
63
70
  relation_model = __send__(relation_name)
64
71
  return if relation_model.blank?
65
72
 
66
- addition = -state_data.fetch(:delta_original)
73
+ addition = -state.delta_original
67
74
 
68
75
  if addition != 0
69
76
  primary_key_value = relation_model.read_attribute(relation_model.class.primary_key)
70
- relation_model.class.update_counters(primary_key_value, args.fetch(:column_name) => addition)
77
+ relation_model.class.update_counters(primary_key_value, counter_cache.column_name => addition) # rubocop:disable Rails/SkipsModelValidations
71
78
  end
72
79
  end
73
80
 
74
- def update_awesome_counter_cache_for(relation_name, state_data, args)
75
- relation_model = __send__(relation_name)
76
- return if relation_model.blank?
77
-
78
- addition = state_data.fetch(:delta_current) - state_data.fetch(:delta_original)
79
-
80
- if addition != 0
81
- primary_key_value = relation_model.read_attribute(relation_model.class.primary_key)
82
- relation_model.class.update_counters(primary_key_value, args.fetch(:column_name) => addition)
81
+ def update_awesome_counter_cache_for(relation_name, state, counter_cache) # rubocop:disable Metrics/AbcSize
82
+ addition = state.delta_current - state.delta_original
83
+ relation_model_class = self.class.reflections.fetch(relation_name.to_s).klass
84
+ primary_key_value = read_attribute(counter_cache.relation_foreign_key)
85
+
86
+ if saved_changes.key?(counter_cache.relation_foreign_key)
87
+ # Record change from one to another - reduce and increase based on previously recorded values
88
+ old_record_id = saved_changes.fetch(counter_cache.relation_foreign_key).first
89
+
90
+ if old_record_id && !state.delta_original.zero?
91
+ # Reduce the count of the previous record
92
+ relation_model_class.update_counters(old_record_id, counter_cache.column_name => -state.delta_original) # rubocop:disable Rails/SkipsModelValidations
93
+ end
94
+
95
+ unless state.delta_current.zero?
96
+ # Increase the count of the new record
97
+ relation_model_class.update_counters(primary_key_value, counter_cache.column_name => state.delta_current) # rubocop:disable Rails/SkipsModelValidations
98
+ end
99
+ elsif !addition.zero?
100
+ # Add to the current record
101
+ relation_model_class.update_counters(primary_key_value, counter_cache.column_name => addition) # rubocop:disable Rails/SkipsModelValidations
83
102
  end
84
103
  end
85
104
  end
@@ -0,0 +1,3 @@
1
+ class AwesomeCounterCache::State
2
+ attr_accessor :delta_current, :delta_original
3
+ end
@@ -1,3 +1,3 @@
1
1
  module AwesomeCounterCache
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2".freeze
3
3
  end
@@ -2,7 +2,9 @@ module AwesomeCounterCache
2
2
  extend ActiveSupport::Autoload
3
3
 
4
4
  autoload :ClassMethods
5
+ autoload :CounterCache
5
6
  autoload :InstanceMethods
7
+ autoload :State
6
8
 
7
9
  def self.included(base)
8
10
  base.extend AwesomeCounterCache::ClassMethods
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awesome_counter_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-07 00:00:00.000000000 Z
11
+ date: 2023-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: factory_bot_rails
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mysql2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: pry
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +128,48 @@ dependencies:
100
128
  - - ">="
101
129
  - !ruby/object:Gem::Version
102
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop-performance
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rubocop-rails
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: rubocop-rspec
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
103
173
  - !ruby/object:Gem::Dependency
104
174
  name: sqlite3
105
175
  requirement: !ruby/object:Gem::Requirement
@@ -140,13 +210,16 @@ files:
140
210
  - Rakefile
141
211
  - lib/awesome_counter_cache.rb
142
212
  - lib/awesome_counter_cache/class_methods.rb
213
+ - lib/awesome_counter_cache/counter_cache.rb
143
214
  - lib/awesome_counter_cache/instance_methods.rb
215
+ - lib/awesome_counter_cache/state.rb
144
216
  - lib/awesome_counter_cache/version.rb
145
217
  - lib/tasks/awesome_counter_cache_tasks.rake
146
218
  homepage: https://github.com/kaspernj/awesome_counter_cache
147
219
  licenses:
148
220
  - MIT
149
- metadata: {}
221
+ metadata:
222
+ rubygems_mfa_required: 'true'
150
223
  post_install_message:
151
224
  rdoc_options: []
152
225
  require_paths:
@@ -155,14 +228,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
228
  requirements:
156
229
  - - ">="
157
230
  - !ruby/object:Gem::Version
158
- version: '0'
231
+ version: 2.5.0
159
232
  required_rubygems_version: !ruby/object:Gem::Requirement
160
233
  requirements:
161
234
  - - ">="
162
235
  - !ruby/object:Gem::Version
163
236
  version: '0'
164
237
  requirements: []
165
- rubygems_version: 3.0.6
238
+ rubygems_version: 3.0.8
166
239
  signing_key:
167
240
  specification_version: 4
168
241
  summary: Counter caching with a bit more for Rails