awesome_counter_cache 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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