running_count 0.1.0 → 0.2.0

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: 281c3126d219fffe217bea334f4ee81b040bb875ea1d5b120a5443eff7db48fa
4
- data.tar.gz: b236cc36eaec448d824371484cb1c0505d7fc1170324ba105cd04722de566a15
3
+ metadata.gz: 17316e1fc11a06d992f032a266cfdd460e2398d9f2ea2cd012e12ccda8d6e6bf
4
+ data.tar.gz: 6c2c23a38cf332a8a164642b595b78bcbc7b895a26513b2244b2b4c2c3489089
5
5
  SHA512:
6
- metadata.gz: 0ce7b753f6c6d2a2a8b6334bb17aaed7b3856a499716a85a01d4c6af6df24896b043f6af381fc2d314c5c548dc191777ee186cb19fe9d9462e44ee4e4416f725
7
- data.tar.gz: afe63389d76ee143a0df841d4c6480e23e3560e913bddf7603c4f6f6555710f61fc62fe4ac993a677c7d2c7e7a5f21a45f210c99cabc17b6550497497fbcf944
6
+ metadata.gz: b2081c854ebba5b361c9c7e40fbc73a51de2201d76cb28a91efa4b70a508d71e88dc74bd516d770fa7c6d10deb05ab1bd8842c466b5c1c542f123adf178fd650
7
+ data.tar.gz: e8a44b425b3726484fd246bf171149329dffcd2da868573ce9e9ccac10b916c98e28b5ba1ff7c50cff9fc5eac98e4a36c2e9d7f62c6cd7cc9515f789b8ec037b
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- running_count (0.1.0)
5
- activesupport
4
+ running_count (0.2.0)
5
+ activesupport (~> 4.2.11)
6
6
  pg (= 0.20.0)
7
- redis-rails
7
+ redis-rails (~> 5.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -74,8 +74,6 @@ GEM
74
74
  pry-byebug (3.6.0)
75
75
  byebug (~> 10.0)
76
76
  pry (~> 0.10)
77
- pry-rails (0.3.9)
78
- pry (>= 0.10.4)
79
77
  rack (1.6.11)
80
78
  rack-test (0.6.3)
81
79
  rack (>= 1.0)
@@ -150,9 +148,8 @@ PLATFORMS
150
148
  ruby
151
149
 
152
150
  DEPENDENCIES
153
- database_cleaner
154
- pry-byebug
155
- pry-rails
151
+ database_cleaner (~> 1.7.0)
152
+ pry-byebug (~> 3.6.0)
156
153
  rails (~> 4.0)
157
154
  rake (~> 10.0)
158
155
  rspec (~> 3.0)
data/README.md CHANGED
@@ -1,28 +1,45 @@
1
- # RunningCount
1
+ # running_count
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/running_count`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Counter caches for Rails applications, including cached running counts.
6
4
 
7
5
  ## Installation
8
6
 
9
7
  Add this line to your application's Gemfile:
10
8
 
11
9
  ```ruby
12
- gem 'running_count'
10
+ gem 'running_count', '~> 0.2`
13
11
  ```
14
12
 
15
13
  And then execute:
16
14
 
17
15
  $ bundle
18
16
 
19
- Or install it yourself as:
17
+ ## Usage
20
18
 
21
- $ gem install running_count
19
+ ```
20
+ class Course < ActiveRecord::Base
21
+ belongs_to :user
22
22
 
23
- ## Usage
23
+ keep_running_count :user
24
+ end
25
+
26
+ class User
27
+ has_many :courses
28
+ end
29
+ ```
30
+
31
+ Tracks the number of Course records associated with the User model, saving them to the `courses_count` field in the 'users' table.
32
+
33
+ Also tracks a dynamic running count in the `running_courses_count` method on the `User` model.
34
+
35
+ ## Reconciling changes
36
+
37
+ ```
38
+ Course.reconcile_changes
39
+ ```
40
+
41
+ Will update the 'users' table with the number of associated courses in the `courses_count` field, and clear the dynamic cache.
24
42
 
25
- TODO: Write usage instructions here
26
43
 
27
44
  ## Development
28
45
 
@@ -5,28 +5,33 @@ module RunningCount
5
5
 
6
6
  extend ActiveSupport::Concern
7
7
 
8
- def enqueue_count
9
- Counter.enqueue_change(self, self.class._counter_data)
8
+ def enqueue_changes
9
+ Counter.enqueue_changes(self, self.class._counter_data)
10
10
  end
11
11
 
12
- def enqueue_sum
13
- Counter.enqueue_sum(self, self.class._counter_data)
12
+ def enqueue_deletion
13
+ Counter.enqueue_deletion(self, self.class._counter_data)
14
14
  end
15
15
 
16
16
  module ClassMethods
17
17
 
18
18
  def keep_running_count(relation, opts = {})
19
- Counter.add_callbacks(self, opts)
19
+ data = Counter.counter_data(self.name, self.table_name, relation, opts)
20
+ counter_column = data[:counter_column]
21
+
22
+ _counter_data[counter_column] = data
20
23
 
21
- @counter_data = Counter.counter_data(self.name, self.table_name, relation, opts)
24
+ Counter.add_callbacks(self, opts)
22
25
  end
23
26
 
24
27
  def reconcile_changes
25
- Counter.reconcile_changes(self._counter_data)
28
+ self._counter_data.values.each do |data|
29
+ Counter.reconcile_changes(data)
30
+ end
26
31
  end
27
32
 
28
33
  def _counter_data
29
- @counter_data
34
+ @counter_data ||= {}
30
35
  end
31
36
 
32
37
  end
@@ -5,6 +5,16 @@ module RunningCount
5
5
 
6
6
  class << self
7
7
 
8
+ def enqueue_changes(record, counter_data)
9
+ counter_data
10
+ .values
11
+ .partition { |data| data[:aggregated_field].present? }
12
+ .tap do |sums, counts|
13
+ sums.each { |data| Counter.enqueue_sum(record, data) }
14
+ counts.each { |data| Counter.enqueue_count(record, data) }
15
+ end
16
+ end
17
+
8
18
  def enqueue_sum(record, counter_data)
9
19
  aggregated_field = counter_data[:aggregated_field]
10
20
 
@@ -13,17 +23,35 @@ module RunningCount
13
23
  diff = record.previous_changes[aggregated_field].last.to_i - record.previous_changes[aggregated_field].first.to_i
14
24
 
15
25
  if diff != 0
16
- Counter.enqueue_change(record, counter_data.merge(amount: diff))
26
+ Counter.enqueue_count(record, counter_data.merge(amount: diff))
17
27
  end
18
28
  end
19
29
 
20
- def enqueue_change(record, counter_data)
30
+ def enqueue_count(record, counter_data)
31
+ if changed_field = counter_data[:changed_field]
32
+ return true unless record.previous_changes.has_key?(changed_field) && counter_data[:if].call(record)
33
+ end
34
+
21
35
  destination = record.send(counter_data[:relation])
22
36
  item = Format.item(destination)
23
37
 
24
38
  Storage.add_item(item, counter_data[:running_set_name], counter_data.fetch(:amount, 1))
25
- rescue StandardError => e
26
- binding.pry
39
+ end
40
+
41
+ def enqueue_deletion(record, counter_data)
42
+ counter_data
43
+ .values
44
+ .each do |data|
45
+ Counter.enqueue_single_delete(record, data)
46
+ end
47
+ end
48
+
49
+ def enqueue_single_delete(record, data)
50
+ destination = record.send(data[:relation])
51
+ item = Format.item(destination)
52
+ amount = amount_from_deleted_record(record, data)
53
+
54
+ Storage.add_item(item, data[:running_set_name], 0 - amount)
27
55
  end
28
56
 
29
57
  def reconcile_changes(counter_data)
@@ -73,21 +101,27 @@ module RunningCount
73
101
  statement: statement,
74
102
  release_sql: Statement.release_sql(statement),
75
103
  aggregated_field: opts[:aggregated_field],
104
+ changed_field: opts[:changed_field],
76
105
  statement_sql: sql,
77
106
  if: opts[:if],
78
107
  }
79
108
  end
80
109
 
81
110
  def add_callbacks(klass, opts)
82
- if opts[:aggregated_field]
83
- klass.after_commit :enqueue_sum, on: [:create, :update], if: opts[:if]
84
- else
85
- klass.after_commit :enqueue_count, on: [:create, :update], if: opts[:if]
86
- end
111
+ klass.after_commit :enqueue_changes, on: [:create, :update], if: opts[:if]
112
+ klass.after_commit :enqueue_deletion, on: [:destroy], if: opts[:if]
87
113
  end
88
114
 
89
115
  private
90
116
 
117
+ def amount_from_deleted_record(record, counter_data)
118
+ if counter_data[:aggregated_field]
119
+ record.send(counter_data[:aggregated_field])
120
+ else
121
+ counter_data.fetch(:amount, 1)
122
+ end
123
+ end
124
+
91
125
  def destination_class_name(relation, opts)
92
126
  opts[:class_name] ? opts[:class_name].to_s.constantize : relation.to_s.camelcase.constantize
93
127
  end
@@ -31,7 +31,6 @@ module RunningCount
31
31
 
32
32
  destination_id = Format.parse(item)
33
33
  ActiveRecord::Base.connection.exec_query("EXECUTE #{counter_data[:statement]}(#{destination_id})")
34
- rescue StandardError => e
35
34
  end
36
35
 
37
36
  private
@@ -56,7 +55,7 @@ module RunningCount
56
55
 
57
56
  def sum_inner_sql(table_name, relation, opts)
58
57
  %(
59
- SELECT SUM(#{opts[:aggregated_field]}) FROM "#{table_name}"
58
+ SELECT COALESCE(SUM(#{opts[:aggregated_field]}), 0) FROM "#{table_name}"
60
59
  WHERE "#{table_name}"."#{relation}_id" = $1
61
60
  #{extra_sql(opts)}
62
61
  )
@@ -1,3 +1,3 @@
1
1
  module RunningCount
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -36,14 +36,13 @@ Gem::Specification.new do |spec|
36
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ["lib"]
38
38
 
39
- spec.add_dependency "activesupport"
40
- spec.add_dependency "redis-rails"
39
+ spec.add_dependency "activesupport", "~> 4.2.11"
40
+ spec.add_dependency "redis-rails", "~> 5.0"
41
41
  spec.add_dependency "pg", "0.20.0"
42
42
 
43
43
  spec.add_development_dependency "rake", "~> 10.0"
44
44
  spec.add_development_dependency "rspec", "~> 3.0"
45
45
  spec.add_development_dependency "rails", "~> 4.0"
46
- spec.add_development_dependency "database_cleaner"
47
- spec.add_development_dependency "pry-rails"
48
- spec.add_development_dependency "pry-byebug"
46
+ spec.add_development_dependency "database_cleaner", "~> 1.7.0"
47
+ spec.add_development_dependency "pry-byebug", "~> 3.6.0"
49
48
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: running_count
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Isaac Priestley
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-31 00:00:00.000000000 Z
11
+ date: 2019-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 4.2.11
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 4.2.11
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: redis-rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pg
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -98,44 +98,30 @@ dependencies:
98
98
  name: database_cleaner
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: pry-rails
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
101
+ - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: '0'
103
+ version: 1.7.0
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
- - - ">="
108
+ - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: '0'
110
+ version: 1.7.0
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: pry-byebug
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
- - - ">="
115
+ - - "~>"
130
116
  - !ruby/object:Gem::Version
131
- version: '0'
117
+ version: 3.6.0
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
- - - ">="
122
+ - - "~>"
137
123
  - !ruby/object:Gem::Version
138
- version: '0'
124
+ version: 3.6.0
139
125
  description: Write a longer description or delete this line.
140
126
  email:
141
127
  - isaac@teachable.com