rollups 0.1.4 → 0.3.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 +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
|