rollups 0.1.4 → 0.3.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/CHANGELOG.md +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +20 -2
- data/lib/generators/rollups_generator.rb +1 -5
- data/lib/rollup/aggregator.rb +23 -19
- data/lib/rollup/version.rb +1 -1
- data/lib/rollups.rb +5 -5
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13842cdbcce3b4b43bd7d8aeb91f1e7af030cdf17d3e030f1bfe8d30eadc3bf4
|
4
|
+
data.tar.gz: e86af13b7e72c7e236d341b5b46158389ae4c8f7425b1580d94b8969e22656c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c8a4add9c0e04504260e64db82573d131dd666f97ff5c7e6b9ea7dc6b28cf24a70c03e5b6ba67eb01539d66cf0ae915c76c1cfc69f7cbe7b56d78fc49f871dc
|
7
|
+
data.tar.gz: 582ed4c461e377e3fc1afa38f03c6c2cfcb0e4d08bfa0aa3b959cf8488731edc36d7371ee2a1ac5ba9ab63cdec90fb65ccc78283b6571ccd3124f472aad27244
|
data/CHANGELOG.md
CHANGED
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
|
@@ -213,6 +219,12 @@ If a series has dimensions, they must match exactly as well
|
|
213
219
|
Rollup.series("Orders by platform and channel", dimensions: {platform: "Web", channel: "Search"})
|
214
220
|
```
|
215
221
|
|
222
|
+
Get a specific time range
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
Rollup.where(time: Date.current.all_year).series("New Users")
|
226
|
+
```
|
227
|
+
|
216
228
|
### Multiple Series
|
217
229
|
|
218
230
|
*PostgreSQL only*
|
@@ -235,6 +247,12 @@ Filter by dimensions
|
|
235
247
|
Rollup.where_dimensions(platform: "Web").multi_series("Orders by platform and channel")
|
236
248
|
```
|
237
249
|
|
250
|
+
Get a specific time range
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
Rollup.where(time: Date.current.all_year).multi_series("Orders by platform")
|
254
|
+
```
|
255
|
+
|
238
256
|
### Raw Data
|
239
257
|
|
240
258
|
Uses the `Rollup` model to query the data directly
|
@@ -25,10 +25,6 @@ class RollupsGenerator < Rails::Generators::Base
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def adapter
|
28
|
-
|
29
|
-
ActiveRecord::Base.connection_db_config.adapter.to_s
|
30
|
-
else
|
31
|
-
ActiveRecord::Base.connection_config[:adapter].to_s
|
32
|
-
end
|
28
|
+
ActiveRecord::Base.connection_db_config.adapter.to_s
|
33
29
|
end
|
34
30
|
end
|
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,6 +56,10 @@ 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
|
@@ -171,16 +183,8 @@ class Rollup
|
|
171
183
|
conflict_target = [:name, :interval, :time]
|
172
184
|
conflict_target << :dimensions if Utils.dimensions_supported?
|
173
185
|
|
174
|
-
|
175
|
-
|
176
|
-
Rollup.unscoped.upsert_all(records, **options)
|
177
|
-
else
|
178
|
-
update = Utils.mysql? ? [:value] : {columns: [:value], conflict_target: conflict_target}
|
179
|
-
Rollup.unscoped.import(records,
|
180
|
-
on_duplicate_key_update: update,
|
181
|
-
validate: false
|
182
|
-
)
|
183
|
-
end
|
186
|
+
options = Utils.mysql? ? {} : {unique_by: conflict_target}
|
187
|
+
Rollup.unscoped.upsert_all(records, **options)
|
184
188
|
end
|
185
189
|
end
|
186
190
|
end
|
data/lib/rollup/version.rb
CHANGED
data/lib/rollups.rb
CHANGED
@@ -4,14 +4,14 @@ require "groupdate"
|
|
4
4
|
|
5
5
|
ActiveSupport.on_load(:active_record) do
|
6
6
|
# must come first
|
7
|
-
|
7
|
+
require_relative "rollup"
|
8
8
|
|
9
|
-
|
9
|
+
require_relative "rollup/model"
|
10
10
|
extend Rollup::Model
|
11
11
|
Rollup.rollup_column = :time
|
12
12
|
|
13
13
|
# modules
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
require_relative "rollup/aggregator"
|
15
|
+
require_relative "rollup/utils"
|
16
|
+
require_relative "rollup/version"
|
17
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rollups
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.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: 2023-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.1'
|
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: '6.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: groupdate
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '6.1'
|
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: '
|
40
|
+
version: '6.1'
|
41
41
|
description:
|
42
42
|
email: andrew@ankane.org
|
43
43
|
executables: []
|
@@ -68,14 +68,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
68
|
requirements:
|
69
69
|
- - ">="
|
70
70
|
- !ruby/object:Gem::Version
|
71
|
-
version: '
|
71
|
+
version: '3'
|
72
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
|
-
rubygems_version: 3.
|
78
|
+
rubygems_version: 3.4.10
|
79
79
|
signing_key:
|
80
80
|
specification_version: 4
|
81
81
|
summary: Rollup time-series data in Rails
|