ar_aggregate_by_interval 1.1.0 → 1.1.2
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/lib/ar_aggregate_by_interval.rb +6 -1
- data/lib/ar_aggregate_by_interval/query_result.rb +12 -3
- data/lib/ar_aggregate_by_interval/query_runner.rb +2 -2
- data/lib/ar_aggregate_by_interval/utils.rb +2 -2
- data/lib/ar_aggregate_by_interval/version.rb +1 -1
- data/spec/ar_bootstrap/init.rb +13 -0
- data/spec/{schema.rb → ar_bootstrap/schema.rb} +8 -2
- data/spec/lib/ar_aggregate_by_interval/query_runner_spec.rb +3 -8
- data/spec/lib/ar_aggregate_by_interval_spec.rb +45 -21
- data/spec/spec_helper.rb +2 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 600ccd6f3d13f4614f3be8a977397114501d1587
|
4
|
+
data.tar.gz: 00eff7b135ab7af2bf368cad7c46ccc6a6e40bd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba67a323ed7e60c81d39cf2c751b2fe3c696bd51be706470bd567efdc90603bd8cd805fda3dfe155157a833bc9b957fa1bbd072eb274377549636f3f87e8b19f
|
7
|
+
data.tar.gz: 13c00d4056ea7d4fd49d2b4a12545f8a378614b21e1e427d6c1330e9f69ed1f4a75b8923049d85c4deda9423158560ad1d632050ffc80880baa708bb617c7e09
|
@@ -24,6 +24,11 @@ module ArAggregateByInterval
|
|
24
24
|
|
25
25
|
return super unless hash_args
|
26
26
|
|
27
|
+
# convert strings to symbols
|
28
|
+
[:group_by_column, :aggregate_column].each do |col|
|
29
|
+
hash_args[col] = hash_args[col].intern if hash_args[col]
|
30
|
+
end
|
31
|
+
|
27
32
|
QueryRunner.new(self, {
|
28
33
|
aggregate_function: aggregate_function,
|
29
34
|
interval: interval
|
@@ -36,4 +41,4 @@ end
|
|
36
41
|
# for queries on the class
|
37
42
|
ActiveRecord::Base.send :extend, ArAggregateByInterval
|
38
43
|
# for scoped queries
|
39
|
-
ActiveRecord::Relation.send :include, ArAggregateByInterval
|
44
|
+
ActiveRecord::Relation.send :include, ArAggregateByInterval
|
@@ -9,7 +9,7 @@ module ArAggregateByInterval
|
|
9
9
|
class QueryResult
|
10
10
|
|
11
11
|
VALID_HASH_ARGS = {
|
12
|
-
ar_result: -> (v) { v.
|
12
|
+
ar_result: -> (v) { v.respond_to?(:to_a) },
|
13
13
|
|
14
14
|
# hash with 1 key where the key is a date column and value is the column being aggegated
|
15
15
|
ar_result_select_col_mapping: -> (v) { v.is_a?(Hash) && v.size == 1 },
|
@@ -21,7 +21,7 @@ module ArAggregateByInterval
|
|
21
21
|
}
|
22
22
|
|
23
23
|
def initialize(args)
|
24
|
-
|
24
|
+
validate_args!(args)
|
25
25
|
|
26
26
|
@dates_values_hash = Utils.ar_to_hash(args[:ar_result], args[:ar_result_select_col_mapping])
|
27
27
|
@date_iterator_method = Utils::DATE_ITERATOR_METHOD_MAP[args[:interval]]
|
@@ -44,6 +44,15 @@ module ArAggregateByInterval
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
+
def validate_args!(hash_args)
|
48
|
+
ClassyHash.validate(hash_args, VALID_HASH_ARGS)
|
49
|
+
first_res = hash_args[:ar_result].first
|
50
|
+
keys = hash_args[:ar_result_select_col_mapping].to_a.flatten
|
51
|
+
if first_res && keys.any? { |key| !first_res.respond_to?(key) }
|
52
|
+
raise RuntimeError.new("the collection passed does not respond to all attribs: #{keys}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
47
56
|
def array_of_dates
|
48
57
|
@array_of_dates ||= @from.to_date.send(@date_iterator_method, @to.to_date).map do |date|
|
49
58
|
[date, date.strftime(@strftime_format)]
|
@@ -52,4 +61,4 @@ module ArAggregateByInterval
|
|
52
61
|
|
53
62
|
end
|
54
63
|
|
55
|
-
end
|
64
|
+
end
|
@@ -11,12 +11,12 @@ module ArAggregateByInterval
|
|
11
11
|
VALID_HASH_ARGS = {
|
12
12
|
aggregate_function: [String], # sum, count
|
13
13
|
interval: [String], # daily, weekly, monthly
|
14
|
-
group_by_column: [
|
14
|
+
group_by_column: [Symbol], # i.e.: :created_at
|
15
15
|
|
16
16
|
from: [Date, DateTime, Time, ActiveSupport::TimeWithZone],
|
17
17
|
to: [:optional, Date, DateTime, Time, ActiveSupport::TimeWithZone],
|
18
18
|
|
19
|
-
aggregate_column: [:optional,
|
19
|
+
aggregate_column: [:optional, Symbol, NilClass] # required when using sum (as opposed to count)
|
20
20
|
}
|
21
21
|
|
22
22
|
attr_reader :values, :values_and_dates
|
@@ -33,10 +33,10 @@ module ArAggregateByInterval
|
|
33
33
|
end
|
34
34
|
|
35
35
|
return {
|
36
|
-
group_by_column: group_by_column,
|
36
|
+
group_by_column: group_by_column.try(:intern),
|
37
37
|
from: from,
|
38
38
|
to: to,
|
39
|
-
aggregate_column: aggregate_column
|
39
|
+
aggregate_column: aggregate_column.try(:intern)
|
40
40
|
}.delete_if { |k, v| v.nil? }
|
41
41
|
end
|
42
42
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
|
4
|
+
|
5
|
+
load File.join(File.dirname(__FILE__), './schema.rb')
|
6
|
+
|
7
|
+
class Blog < ActiveRecord::Base
|
8
|
+
has_many :page_views
|
9
|
+
end
|
10
|
+
|
11
|
+
class PageView < ActiveRecord::Base
|
12
|
+
belongs_to :blog
|
13
|
+
end
|
@@ -3,9 +3,15 @@
|
|
3
3
|
ActiveRecord::Schema.define do
|
4
4
|
self.verbose = false
|
5
5
|
|
6
|
-
create_table :blogs, :
|
6
|
+
create_table :blogs, force: true do |t|
|
7
7
|
t.integer :arbitrary_number
|
8
8
|
t.timestamps null: false
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
create_table :page_views, force: true do |t|
|
12
|
+
t.references :blog
|
13
|
+
t.datetime :date
|
14
|
+
t.integer :count
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -1,9 +1,4 @@
|
|
1
1
|
require 'ar_aggregate_by_interval/query_runner'
|
2
|
-
require 'active_record'
|
3
|
-
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
4
|
-
load File.join(File.dirname(__FILE__), '../../schema.rb')
|
5
|
-
|
6
|
-
class Blog < ActiveRecord::Base; end
|
7
2
|
|
8
3
|
module ArAggregateByInterval
|
9
4
|
describe QueryRunner do
|
@@ -13,7 +8,7 @@ module ArAggregateByInterval
|
|
13
8
|
aggregate_function: aggregate_function,
|
14
9
|
aggregate_column: (aggregate_column rescue nil),
|
15
10
|
interval: interval,
|
16
|
-
group_by_column:
|
11
|
+
group_by_column: :created_at,
|
17
12
|
from: from,
|
18
13
|
to: to
|
19
14
|
})
|
@@ -36,7 +31,7 @@ module ArAggregateByInterval
|
|
36
31
|
context 'avg daily' do
|
37
32
|
let(:interval) { 'daily' }
|
38
33
|
let(:aggregate_function) { 'avg' }
|
39
|
-
let(:aggregate_column) {
|
34
|
+
let(:aggregate_column) { :arbitrary_number }
|
40
35
|
|
41
36
|
describe '.values' do
|
42
37
|
it 'returns an array of size 7' do
|
@@ -68,4 +63,4 @@ module ArAggregateByInterval
|
|
68
63
|
end
|
69
64
|
end
|
70
65
|
|
71
|
-
end
|
66
|
+
end
|
@@ -1,26 +1,22 @@
|
|
1
|
-
require 'active_record'
|
2
1
|
require 'ar_aggregate_by_interval'
|
3
|
-
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
4
|
-
load File.join(File.dirname(__FILE__), '../schema.rb')
|
5
|
-
|
6
|
-
class Blog < ActiveRecord::Base; end
|
7
2
|
|
8
3
|
describe ArAggregateByInterval do
|
9
4
|
|
10
5
|
before(:all) do |example|
|
11
6
|
@from = DateTime.parse '2013-08-05'
|
12
7
|
@to = @from
|
13
|
-
Blog.create arbitrary_number: 10, created_at: @from
|
8
|
+
blog = Blog.create arbitrary_number: 10, created_at: @from
|
9
|
+
blog.page_views.create date: @from
|
14
10
|
end
|
15
11
|
|
16
12
|
shared_examples_for 'count .values_and_dates' do
|
17
|
-
it 'returns value and date with expected values' do
|
13
|
+
it 'returns value and date with expected values' do
|
18
14
|
expect(subject.values_and_dates).to eq([date: @from.beginning_of_week.to_date, value: 1])
|
19
15
|
end
|
20
16
|
end
|
21
17
|
|
22
18
|
shared_examples_for 'sum .values_and_dates' do
|
23
|
-
it 'returns value and date with expected values' do
|
19
|
+
it 'returns value and date with expected values' do
|
24
20
|
expect(subject.values_and_dates).to eq([date: @from.beginning_of_week.to_date, value: 10])
|
25
21
|
end
|
26
22
|
end
|
@@ -31,9 +27,18 @@ describe ArAggregateByInterval do
|
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
|
-
context 'scoped' do
|
30
|
+
context 'ActiveRecord::Relation scoped' do
|
31
|
+
subject do
|
32
|
+
# `where` returns ActiveRecord::Relation
|
33
|
+
Blog.where('id > 0').count_weekly(:created_at, @from, @from)
|
34
|
+
end
|
35
|
+
it_behaves_like 'count .values_and_dates'
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Array scoped' do
|
35
39
|
subject do
|
36
|
-
|
40
|
+
# `associations` return arrays
|
41
|
+
Blog.first.page_views.count_weekly(:date, @from, @from)
|
37
42
|
end
|
38
43
|
it_behaves_like 'count .values_and_dates'
|
39
44
|
end
|
@@ -43,7 +48,7 @@ describe ArAggregateByInterval do
|
|
43
48
|
context 'for count' do
|
44
49
|
subject do
|
45
50
|
Blog.count_weekly({
|
46
|
-
group_by_column:
|
51
|
+
group_by_column: :created_at,
|
47
52
|
from: @from,
|
48
53
|
to: @to
|
49
54
|
})
|
@@ -54,20 +59,32 @@ describe ArAggregateByInterval do
|
|
54
59
|
context 'for sum' do
|
55
60
|
subject do
|
56
61
|
Blog.sum_weekly({
|
57
|
-
group_by_column:
|
58
|
-
aggregate_column:
|
62
|
+
group_by_column: :created_at,
|
63
|
+
aggregate_column: :arbitrary_number,
|
59
64
|
from: @from,
|
60
65
|
to: @to
|
61
66
|
})
|
62
67
|
end
|
63
68
|
it_behaves_like 'sum .values_and_dates'
|
69
|
+
|
70
|
+
context 'with strings' do
|
71
|
+
subject do
|
72
|
+
Blog.sum_weekly({
|
73
|
+
group_by_column: 'created_at',
|
74
|
+
aggregate_column: 'arbitrary_number',
|
75
|
+
from: @from,
|
76
|
+
to: @to
|
77
|
+
})
|
78
|
+
end
|
79
|
+
it_behaves_like 'sum .values_and_dates'
|
80
|
+
end
|
64
81
|
end
|
65
82
|
|
66
83
|
context 'for avg' do
|
67
84
|
subject do
|
68
85
|
Blog.avg_weekly({
|
69
|
-
group_by_column:
|
70
|
-
aggregate_column:
|
86
|
+
group_by_column: :created_at,
|
87
|
+
aggregate_column: :arbitrary_number,
|
71
88
|
from: @from,
|
72
89
|
to: @to
|
73
90
|
})
|
@@ -80,19 +97,26 @@ describe ArAggregateByInterval do
|
|
80
97
|
context 'normal args' do
|
81
98
|
context 'for count' do
|
82
99
|
subject do
|
83
|
-
Blog.count_weekly(
|
100
|
+
Blog.count_weekly(:created_at, @from, @from)
|
84
101
|
end
|
85
102
|
it_behaves_like 'count .values_and_dates'
|
86
103
|
end
|
87
104
|
context 'for sum' do
|
88
105
|
subject do
|
89
|
-
Blog.sum_weekly(
|
106
|
+
Blog.sum_weekly(:created_at, :arbitrary_number, @from, @from)
|
90
107
|
end
|
91
108
|
it_behaves_like 'sum .values_and_dates'
|
109
|
+
|
110
|
+
context 'with strings' do
|
111
|
+
subject do
|
112
|
+
Blog.sum_weekly('created_at', 'arbitrary_number', @from, @from)
|
113
|
+
end
|
114
|
+
it_behaves_like 'sum .values_and_dates'
|
115
|
+
end
|
92
116
|
end
|
93
117
|
context 'for avg' do
|
94
118
|
subject do
|
95
|
-
Blog.avg_weekly(
|
119
|
+
Blog.avg_weekly(:created_at, :arbitrary_number, @from, @from)
|
96
120
|
end
|
97
121
|
it_behaves_like 'avg .values_and_dates'
|
98
122
|
end
|
@@ -101,7 +125,7 @@ describe ArAggregateByInterval do
|
|
101
125
|
context 'bad args' do
|
102
126
|
context 'for count' do
|
103
127
|
subject do
|
104
|
-
Blog.count_weekly(
|
128
|
+
Blog.count_weekly(:created_at, {}, {})
|
105
129
|
end
|
106
130
|
it 'raise NoMethodError' do
|
107
131
|
expect do
|
@@ -112,7 +136,7 @@ describe ArAggregateByInterval do
|
|
112
136
|
|
113
137
|
context 'for sum' do
|
114
138
|
subject do
|
115
|
-
Blog.sum_weekly(
|
139
|
+
Blog.sum_weekly(:created_at, @from, @from)
|
116
140
|
end
|
117
141
|
it 'raise NoMethodError' do
|
118
142
|
expect do
|
@@ -122,4 +146,4 @@ describe ArAggregateByInterval do
|
|
122
146
|
end
|
123
147
|
end
|
124
148
|
|
125
|
-
end
|
149
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar_aggregate_by_interval
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Otto
|
@@ -157,10 +157,11 @@ files:
|
|
157
157
|
- lib/ar_aggregate_by_interval/query_runner.rb
|
158
158
|
- lib/ar_aggregate_by_interval/utils.rb
|
159
159
|
- lib/ar_aggregate_by_interval/version.rb
|
160
|
+
- spec/ar_bootstrap/init.rb
|
161
|
+
- spec/ar_bootstrap/schema.rb
|
160
162
|
- spec/lib/ar_aggregate_by_interval/query_runner_spec.rb
|
161
163
|
- spec/lib/ar_aggregate_by_interval/utils_spec.rb
|
162
164
|
- spec/lib/ar_aggregate_by_interval_spec.rb
|
163
|
-
- spec/schema.rb
|
164
165
|
- spec/spec_helper.rb
|
165
166
|
homepage: https://github.com/jotto/ar_aggregate_by_interval
|
166
167
|
licenses: []
|
@@ -186,8 +187,9 @@ signing_key:
|
|
186
187
|
specification_version: 4
|
187
188
|
summary: add [sum|count]_[daily|weekly|monthly] to your AR models for MySQL AND Postgres
|
188
189
|
test_files:
|
190
|
+
- spec/ar_bootstrap/init.rb
|
191
|
+
- spec/ar_bootstrap/schema.rb
|
189
192
|
- spec/lib/ar_aggregate_by_interval/query_runner_spec.rb
|
190
193
|
- spec/lib/ar_aggregate_by_interval/utils_spec.rb
|
191
194
|
- spec/lib/ar_aggregate_by_interval_spec.rb
|
192
|
-
- spec/schema.rb
|
193
195
|
- spec/spec_helper.rb
|