rollups 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/LICENSE.txt +1 -1
- data/README.md +8 -2
- data/lib/rollup/aggregator.rb +25 -13
- data/lib/rollup/version.rb +1 -1
- data/lib/rollup.rb +1 -1
- data/lib/rollups.rb +1 -0
- metadata +8 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bc765589c1bb3ac755335e36a1a283ef4aeac8ac54a6bc102d3358c57768628
|
4
|
+
data.tar.gz: 0eab24b5cd948823ab190674618fec7ce0935b91d740384854e0474b931d9318
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a64dd7d050f06d49a5d8261b09b0437faf7a579e086b154903daf86de86ad799a1b97c98d44149b0e0fb20e4531a9d435b787adccefff7b89afb91f4cc44af3
|
7
|
+
data.tar.gz: 60ac29b15fb518bfaad4026ca02d55a926a829f1229f758993a07cace6117030247211750fb1bc33deb9547e55e406ab81e1a06f2ecc3f9208d626d62744aa3c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.2.0 (2022-04-05)
|
2
|
+
|
3
|
+
- Added `range` option
|
4
|
+
- Dropped support for Active Record < 5.2
|
5
|
+
|
6
|
+
## 0.1.4 (2021-12-15)
|
7
|
+
|
8
|
+
- Fixed warning with Active Record 7
|
9
|
+
|
10
|
+
## 0.1.3 (2021-10-20)
|
11
|
+
|
12
|
+
- Fixed issue rolling up rollups
|
13
|
+
|
1
14
|
## 0.1.2 (2021-06-07)
|
2
15
|
|
3
16
|
- Fixed deprecation warning with Active Record 6.1
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -11,13 +11,13 @@ Works great with [Ahoy](https://github.com/ankane/ahoy) and [Searchjoy](https://
|
|
11
11
|
Add this line to your application’s Gemfile:
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
gem
|
14
|
+
gem "rollups"
|
15
15
|
```
|
16
16
|
|
17
17
|
For Rails < 6, also add:
|
18
18
|
|
19
19
|
```ruby
|
20
|
-
gem
|
20
|
+
gem "activerecord-import"
|
21
21
|
```
|
22
22
|
|
23
23
|
And run:
|
@@ -173,6 +173,12 @@ To recalculate the last few intervals, use:
|
|
173
173
|
User.rollup("New users", last: 3)
|
174
174
|
```
|
175
175
|
|
176
|
+
To recalculate a time range, use:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
User.rollup("New users", range: 1.week.ago.all_week)
|
180
|
+
```
|
181
|
+
|
176
182
|
To only store data for completed intervals, use:
|
177
183
|
|
178
184
|
```ruby
|
data/lib/rollup/aggregator.rb
CHANGED
@@ -4,13 +4,15 @@ class Rollup
|
|
4
4
|
@klass = klass # or relation
|
5
5
|
end
|
6
6
|
|
7
|
-
def rollup(name, column: nil, interval: "day", dimension_names: nil, time_zone: nil, current:
|
7
|
+
def rollup(name, column: nil, interval: "day", dimension_names: nil, time_zone: nil, current: nil, last: nil, clear: false, range: nil, &block)
|
8
8
|
raise "Name can't be blank" if name.blank?
|
9
9
|
|
10
10
|
column ||= @klass.rollup_column || :created_at
|
11
|
-
|
11
|
+
# Groupdate 6+ validates, but keep this for now for additional safety
|
12
|
+
# no need to quote/resolve column here, as Groupdate handles it
|
13
|
+
column = validate_column(column)
|
12
14
|
|
13
|
-
relation = perform_group(name, column: column, interval: interval, time_zone: time_zone, current: current, last: last, clear: clear)
|
15
|
+
relation = perform_group(name, column: column, interval: interval, time_zone: time_zone, current: current, last: last, clear: clear, range: range)
|
14
16
|
result = perform_calculation(relation, &block)
|
15
17
|
|
16
18
|
dimension_names = set_dimension_names(dimension_names, relation)
|
@@ -23,18 +25,24 @@ class Rollup
|
|
23
25
|
|
24
26
|
# basic version of Active Record disallow_raw_sql!
|
25
27
|
# symbol = column (safe), Arel node = SQL (safe), other = untrusted
|
26
|
-
#
|
27
|
-
# TODO remove this method when gem depends on Groupdate 6+
|
28
|
+
# matches table.column and column
|
28
29
|
def validate_column(column)
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
unless column.is_a?(Symbol) || column.is_a?(Arel::Nodes::SqlLiteral)
|
31
|
+
column = column.to_s
|
32
|
+
unless /\A\w+(\.\w+)?\z/i.match(column)
|
33
|
+
raise ActiveRecord::UnknownAttributeReference, "Query method called with non-attribute argument(s): #{column.inspect}. Use Arel.sql() for known-safe values."
|
34
|
+
end
|
32
35
|
end
|
36
|
+
column
|
33
37
|
end
|
34
38
|
|
35
|
-
def perform_group(name, column:, interval:, time_zone:, current:, last:, clear:)
|
39
|
+
def perform_group(name, column:, interval:, time_zone:, current:, last:, clear:, range:)
|
40
|
+
raise ArgumentError, "Cannot use last and range together" if last && range
|
36
41
|
raise ArgumentError, "Cannot use last and clear together" if last && clear
|
42
|
+
raise ArgumentError, "Cannot use range and clear together" if range && clear
|
43
|
+
raise ArgumentError, "Cannot use range and current together" if range && !current.nil?
|
37
44
|
|
45
|
+
current = true if current.nil?
|
38
46
|
time_zone ||= Rollup.time_zone
|
39
47
|
|
40
48
|
gd_options = {
|
@@ -48,10 +56,14 @@ class Rollup
|
|
48
56
|
|
49
57
|
if last
|
50
58
|
gd_options[:last] = last
|
59
|
+
elsif range
|
60
|
+
gd_options[:range] = range
|
61
|
+
gd_options[:expand_range] = true
|
62
|
+
gd_options.delete(:current)
|
51
63
|
elsif !clear
|
52
64
|
# if no rollups, compute all intervals
|
53
65
|
# if rollups, recompute last interval
|
54
|
-
max_time = Rollup.where(name: name, interval: interval).maximum(Utils.time_sql(interval))
|
66
|
+
max_time = Rollup.unscoped.where(name: name, interval: interval).maximum(Utils.time_sql(interval))
|
55
67
|
if max_time
|
56
68
|
# for MySQL on Ubuntu 18.04 (and likely other platforms)
|
57
69
|
if max_time.is_a?(String)
|
@@ -157,7 +169,7 @@ class Rollup
|
|
157
169
|
def maybe_clear(clear, name, interval)
|
158
170
|
if clear
|
159
171
|
Rollup.transaction do
|
160
|
-
Rollup.where(name: name, interval: interval).delete_all
|
172
|
+
Rollup.unscoped.where(name: name, interval: interval).delete_all
|
161
173
|
yield
|
162
174
|
end
|
163
175
|
else
|
@@ -173,10 +185,10 @@ class Rollup
|
|
173
185
|
|
174
186
|
if ActiveRecord::VERSION::MAJOR >= 6
|
175
187
|
options = Utils.mysql? ? {} : {unique_by: conflict_target}
|
176
|
-
Rollup.upsert_all(records, **options)
|
188
|
+
Rollup.unscoped.upsert_all(records, **options)
|
177
189
|
else
|
178
190
|
update = Utils.mysql? ? [:value] : {columns: [:value], conflict_target: conflict_target}
|
179
|
-
Rollup.import(records,
|
191
|
+
Rollup.unscoped.import(records,
|
180
192
|
on_duplicate_key_update: update,
|
181
193
|
validate: false
|
182
194
|
)
|
data/lib/rollup/version.rb
CHANGED
data/lib/rollup.rb
CHANGED
@@ -75,7 +75,7 @@ class Rollup < ActiveRecord::Base
|
|
75
75
|
# feels cleaner than overriding _read_attribute
|
76
76
|
def inspect
|
77
77
|
if Utils.date_interval?(interval)
|
78
|
-
super.sub(/time: "[^"]+"/, "time: \"#{time.
|
78
|
+
super.sub(/time: "[^"]+"/, "time: \"#{time.to_formatted_s(:db)}\"")
|
79
79
|
else
|
80
80
|
super
|
81
81
|
end
|
data/lib/rollups.rb
CHANGED
metadata
CHANGED
@@ -1,31 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rollups
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '5.1'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '5.1'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: groupdate
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - ">="
|
@@ -39,105 +25,21 @@ dependencies:
|
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: '5.2'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
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: rake
|
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'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '5'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '5'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: activerecord
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pg
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
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: mysql2
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: sqlite3
|
28
|
+
name: groupdate
|
127
29
|
requirement: !ruby/object:Gem::Requirement
|
128
30
|
requirements:
|
129
31
|
- - ">="
|
130
32
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
132
|
-
type: :
|
33
|
+
version: '6.1'
|
34
|
+
type: :runtime
|
133
35
|
prerelease: false
|
134
36
|
version_requirements: !ruby/object:Gem::Requirement
|
135
37
|
requirements:
|
136
38
|
- - ">="
|
137
39
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
40
|
+
version: '6.1'
|
139
41
|
description:
|
140
|
-
email: andrew@
|
42
|
+
email: andrew@ankane.org
|
141
43
|
executables: []
|
142
44
|
extensions: []
|
143
45
|
extra_rdoc_files: []
|
@@ -173,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
75
|
- !ruby/object:Gem::Version
|
174
76
|
version: '0'
|
175
77
|
requirements: []
|
176
|
-
rubygems_version: 3.
|
78
|
+
rubygems_version: 3.3.7
|
177
79
|
signing_key:
|
178
80
|
specification_version: 4
|
179
81
|
summary: Rollup time-series data in Rails
|