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 +4 -4
- data/Gemfile.lock +5 -8
- data/README.md +26 -9
- data/lib/running_count/callbacks.rb +13 -8
- data/lib/running_count/counter.rb +43 -9
- data/lib/running_count/statement.rb +1 -2
- data/lib/running_count/version.rb +1 -1
- data/running_count.gemspec +4 -5
- metadata +18 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17316e1fc11a06d992f032a266cfdd460e2398d9f2ea2cd012e12ccda8d6e6bf
|
4
|
+
data.tar.gz: 6c2c23a38cf332a8a164642b595b78bcbc7b895a26513b2244b2b4c2c3489089
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
#
|
1
|
+
# running_count
|
2
2
|
|
3
|
-
|
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
|
-
|
17
|
+
## Usage
|
20
18
|
|
21
|
-
|
19
|
+
```
|
20
|
+
class Course < ActiveRecord::Base
|
21
|
+
belongs_to :user
|
22
22
|
|
23
|
-
|
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
|
9
|
-
Counter.
|
8
|
+
def enqueue_changes
|
9
|
+
Counter.enqueue_changes(self, self.class._counter_data)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
Counter.
|
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.
|
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
|
-
|
24
|
+
Counter.add_callbacks(self, opts)
|
22
25
|
end
|
23
26
|
|
24
27
|
def reconcile_changes
|
25
|
-
|
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.
|
26
|
+
Counter.enqueue_count(record, counter_data.merge(amount: diff))
|
17
27
|
end
|
18
28
|
end
|
19
29
|
|
20
|
-
def
|
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
|
-
|
26
|
-
|
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[:
|
83
|
-
|
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
|
)
|
data/running_count.gemspec
CHANGED
@@ -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-
|
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.
|
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-
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
124
|
+
version: 3.6.0
|
139
125
|
description: Write a longer description or delete this line.
|
140
126
|
email:
|
141
127
|
- isaac@teachable.com
|