ar_aggregate_by_interval 1.1.0 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|