active_reporter 0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +14 -0
- data/README.md +436 -0
- data/Rakefile +23 -0
- data/lib/active_reporter.rb +26 -0
- data/lib/active_reporter/aggregator.rb +9 -0
- data/lib/active_reporter/aggregator/array.rb +14 -0
- data/lib/active_reporter/aggregator/average.rb +9 -0
- data/lib/active_reporter/aggregator/base.rb +73 -0
- data/lib/active_reporter/aggregator/count.rb +23 -0
- data/lib/active_reporter/aggregator/count_if.rb +23 -0
- data/lib/active_reporter/aggregator/max.rb +9 -0
- data/lib/active_reporter/aggregator/min.rb +9 -0
- data/lib/active_reporter/aggregator/ratio.rb +23 -0
- data/lib/active_reporter/aggregator/sum.rb +13 -0
- data/lib/active_reporter/calculator.rb +2 -0
- data/lib/active_reporter/calculator/base.rb +19 -0
- data/lib/active_reporter/calculator/ratio.rb +9 -0
- data/lib/active_reporter/dimension.rb +8 -0
- data/lib/active_reporter/dimension/base.rb +150 -0
- data/lib/active_reporter/dimension/bin.rb +123 -0
- data/lib/active_reporter/dimension/bin/set.rb +162 -0
- data/lib/active_reporter/dimension/bin/table.rb +43 -0
- data/lib/active_reporter/dimension/category.rb +29 -0
- data/lib/active_reporter/dimension/enum.rb +32 -0
- data/lib/active_reporter/dimension/number.rb +51 -0
- data/lib/active_reporter/dimension/time.rb +93 -0
- data/lib/active_reporter/evaluator.rb +2 -0
- data/lib/active_reporter/evaluator/base.rb +17 -0
- data/lib/active_reporter/evaluator/block.rb +15 -0
- data/lib/active_reporter/inflector.rb +8 -0
- data/lib/active_reporter/invalid_params_error.rb +4 -0
- data/lib/active_reporter/report.rb +102 -0
- data/lib/active_reporter/report/aggregation.rb +297 -0
- data/lib/active_reporter/report/definition.rb +195 -0
- data/lib/active_reporter/report/metrics.rb +75 -0
- data/lib/active_reporter/report/validation.rb +106 -0
- data/lib/active_reporter/serializer.rb +7 -0
- data/lib/active_reporter/serializer/base.rb +103 -0
- data/lib/active_reporter/serializer/csv.rb +22 -0
- data/lib/active_reporter/serializer/form_field.rb +134 -0
- data/lib/active_reporter/serializer/hash_table.rb +12 -0
- data/lib/active_reporter/serializer/highcharts.rb +200 -0
- data/lib/active_reporter/serializer/nested_hash.rb +11 -0
- data/lib/active_reporter/serializer/table.rb +21 -0
- data/lib/active_reporter/tracker.rb +2 -0
- data/lib/active_reporter/tracker/base.rb +15 -0
- data/lib/active_reporter/tracker/delta.rb +9 -0
- data/lib/active_reporter/version.rb +3 -0
- data/lib/tasks/active_reporter_tasks.rake +4 -0
- data/spec/acceptance/data_spec.rb +381 -0
- data/spec/active_reporter/aggregator_spec.rb +102 -0
- data/spec/active_reporter/dimension/base_spec.rb +102 -0
- data/spec/active_reporter/dimension/bin/set_spec.rb +83 -0
- data/spec/active_reporter/dimension/bin/table_spec.rb +47 -0
- data/spec/active_reporter/dimension/bin_spec.rb +77 -0
- data/spec/active_reporter/dimension/category_spec.rb +60 -0
- data/spec/active_reporter/dimension/enum_spec.rb +94 -0
- data/spec/active_reporter/dimension/number_spec.rb +71 -0
- data/spec/active_reporter/dimension/time_spec.rb +61 -0
- data/spec/active_reporter/report_spec.rb +597 -0
- data/spec/active_reporter/serializer/hash_table_spec.rb +45 -0
- data/spec/active_reporter/serializer/highcharts_spec.rb +113 -0
- data/spec/active_reporter/serializer/table_spec.rb +62 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +26 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/site_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/author.rb +4 -0
- data/spec/dummy/app/models/comment.rb +4 -0
- data/spec/dummy/app/models/data_builder.rb +112 -0
- data/spec/dummy/app/models/post.rb +6 -0
- data/spec/dummy/app/models/post_report.rb +14 -0
- data/spec/dummy/app/views/layouts/application.html.erb +17 -0
- data/spec/dummy/app/views/site/report.html.erb +73 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +57 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/migrate/20150714202319_add_dummy_models.rb +25 -0
- data/spec/dummy/db/schema.rb +43 -0
- data/spec/dummy/db/seeds.rb +1 -0
- data/spec/dummy/log/test.log +37033 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/factories.rb +29 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/support/float.rb +8 -0
- metadata +385 -0
@@ -0,0 +1,381 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'more complicated case' do
|
4
|
+
let(:report_model) do
|
5
|
+
Class.new(ActiveReporter::Report) do
|
6
|
+
report_on :Post
|
7
|
+
|
8
|
+
time_dimension :published_at
|
9
|
+
number_dimension :likes
|
10
|
+
category_dimension :author, model: :author, attribute: :name, relation: ->(r) { r.left_outer_joins(:author) }
|
11
|
+
|
12
|
+
count_aggregator :count
|
13
|
+
sum_aggregator :total_likes, attribute: :likes
|
14
|
+
average_aggregator :mean_likes, attribute: :likes
|
15
|
+
min_aggregator :min_likes, attribute: :likes
|
16
|
+
max_aggregator :max_likes, attribute: :likes
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def data_by(groupers, g_params = nil)
|
21
|
+
groupers = Array.wrap(groupers)
|
22
|
+
dimension_params = {}
|
23
|
+
if g_params
|
24
|
+
g_params = Array.wrap(g_params)
|
25
|
+
groupers.zip(g_params).each do |grouper, params|
|
26
|
+
dimension_params[grouper] = params
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
report = report_model.new(groupers: groupers, dimensions: dimension_params)
|
31
|
+
report.data
|
32
|
+
end
|
33
|
+
|
34
|
+
def expect_equal(h1, h2)
|
35
|
+
# sqlite uses Float instead of BigDecimal, we need to normalize the JSON objects to use the
|
36
|
+
# same data type so the values match. We also round these at 9 decimal places to account for
|
37
|
+
# rounding discrepencies between the two data types
|
38
|
+
|
39
|
+
h1_json = JSON.parse(h1.to_json).map do |a|
|
40
|
+
a.deep_transform_values do |v|
|
41
|
+
case v
|
42
|
+
when String
|
43
|
+
BigDecimal(v).round(9) rescue v
|
44
|
+
else
|
45
|
+
v
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
h2_json = JSON.parse(h2.to_json).map do |a|
|
51
|
+
a.deep_transform_values do |v|
|
52
|
+
case v
|
53
|
+
when String
|
54
|
+
BigDecimal(v).round(9) rescue v
|
55
|
+
else
|
56
|
+
v
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
expect(h1_json).to eq h2_json
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:joyce) { create(:author, name: 'James Joyce') }
|
65
|
+
let(:woolf) { create(:author, name: 'Virginia Woolf') }
|
66
|
+
|
67
|
+
let(:oct_1) { Time.zone.parse('2015-10-01') }
|
68
|
+
let(:nov_1) { Time.zone.parse('2015-11-01') }
|
69
|
+
let(:dec_1) { Time.zone.parse('2015-12-01') }
|
70
|
+
|
71
|
+
let(:oct) { { min: oct_1, max: nov_1 } }
|
72
|
+
let(:nov) { { min: nov_1, max: dec_1 } }
|
73
|
+
|
74
|
+
let!(:post_1) { create(:post, author: joyce.name, published_at: oct_1, likes: 1) }
|
75
|
+
let!(:post_2) { create(:post, author: joyce.name, published_at: oct_1, likes: 2) }
|
76
|
+
let!(:post_3) { create(:post, author: joyce.name, published_at: nov_1, likes: 1) }
|
77
|
+
let!(:post_4) { create(:post, author: joyce.name, likes: 3).tap { |p| p.update!(published_at: nil) } }
|
78
|
+
|
79
|
+
let!(:post_5) { create(:post, author: woolf.name, published_at: oct_1, likes: 2) }
|
80
|
+
let!(:post_6) { create(:post, author: woolf.name, published_at: nov_1, likes: 3) }
|
81
|
+
let!(:post_7) { create(:post, author: woolf.name, likes: 3).tap { |p| p.update!(published_at: nil) } }
|
82
|
+
|
83
|
+
let!(:post_8) { create(:post, author: nil, published_at: oct_1, likes: 2) }
|
84
|
+
let!(:post_9) { create(:post, author: nil, published_at: nov_1, likes: 3) }
|
85
|
+
|
86
|
+
specify 'basic grouping, 1 grouper, no filters' do
|
87
|
+
expect_equal data_by(:author), [
|
88
|
+
{ key: nil, values: [
|
89
|
+
{ key: :count, value: 2 },
|
90
|
+
{ key: :total_likes, value: 5 },
|
91
|
+
{ key: :mean_likes, value: '2.5' },
|
92
|
+
{ key: :min_likes, value: 2 },
|
93
|
+
{ key: :max_likes, value: 3 }
|
94
|
+
] },
|
95
|
+
{ key: joyce.name, values: [
|
96
|
+
{ key: :count, value: 4 },
|
97
|
+
{ key: :total_likes, value: 7 },
|
98
|
+
{ key: :mean_likes, value: '1.75' },
|
99
|
+
{ key: :min_likes, value: 1 },
|
100
|
+
{ key: :max_likes, value: 3 }
|
101
|
+
] },
|
102
|
+
{ key: woolf.name, values: [
|
103
|
+
{ key: :count, value: 3 },
|
104
|
+
{ key: :total_likes, value: 8 },
|
105
|
+
{ key: :mean_likes, value: '2.6666666666666667' },
|
106
|
+
{ key: :min_likes, value: 2 },
|
107
|
+
{ key: :max_likes, value: 3 }
|
108
|
+
] }
|
109
|
+
]
|
110
|
+
|
111
|
+
expect_equal data_by(:published_at, bin_width: '1 month'), [
|
112
|
+
{ key: nil, values: [
|
113
|
+
{ key: :count, value: 2 },
|
114
|
+
{ key: :total_likes, value: 6 },
|
115
|
+
{ key: :mean_likes, value: '3.0' },
|
116
|
+
{ key: :min_likes, value: 3 },
|
117
|
+
{ key: :max_likes, value: 3 }
|
118
|
+
] },
|
119
|
+
{ key: oct, values: [
|
120
|
+
{ key: :count, value: 4 },
|
121
|
+
{ key: :total_likes, value: 7 },
|
122
|
+
{ key: :mean_likes, value: '1.75' },
|
123
|
+
{ key: :min_likes, value: 1 },
|
124
|
+
{ key: :max_likes, value: 2 }
|
125
|
+
] },
|
126
|
+
{ key: nov, values: [
|
127
|
+
{ key: :count, value: 3 },
|
128
|
+
{ key: :total_likes, value: 7 },
|
129
|
+
{ key: :mean_likes, value: '2.3333333333333333' },
|
130
|
+
{ key: :min_likes, value: 1 },
|
131
|
+
{ key: :max_likes, value: 3 }
|
132
|
+
] }
|
133
|
+
]
|
134
|
+
|
135
|
+
expect_equal data_by(:likes, bin_width: 1), [
|
136
|
+
{ key: { min: 1, max: 2 }, values: [
|
137
|
+
{ key: :count, value: 2 },
|
138
|
+
{ key: :total_likes, value: 2 },
|
139
|
+
{ key: :mean_likes, value: '1.0' },
|
140
|
+
{ key: :min_likes, value: 1 },
|
141
|
+
{ key: :max_likes, value: 1 }
|
142
|
+
] },
|
143
|
+
{ key: { min: 2, max: 3 }, values: [
|
144
|
+
{ key: :count, value: 3 },
|
145
|
+
{ key: :total_likes, value: 6 },
|
146
|
+
{ key: :mean_likes, value: '2.0' },
|
147
|
+
{ key: :min_likes, value: 2 },
|
148
|
+
{ key: :max_likes, value: 2 }
|
149
|
+
] },
|
150
|
+
{ key: { min: 3, max: 4 }, values: [
|
151
|
+
{ key: :count, value: 4 },
|
152
|
+
{ key: :total_likes, value: 12 },
|
153
|
+
{ key: :mean_likes, value: '3.0' },
|
154
|
+
{ key: :min_likes, value: 3 },
|
155
|
+
{ key: :max_likes, value: 3 }
|
156
|
+
] }
|
157
|
+
]
|
158
|
+
end
|
159
|
+
|
160
|
+
specify 'basic grouping, >=2 groupers, no filters' do
|
161
|
+
expect_equal data_by([:published_at, :author], bin_width: { months: 1 }), [
|
162
|
+
{ key: nil, values: [
|
163
|
+
{ key: nil, values: [
|
164
|
+
{ key: :count, value: 0 },
|
165
|
+
{ key: :total_likes, value: 0 },
|
166
|
+
{ key: :mean_likes, value: nil },
|
167
|
+
{ key: :min_likes, value: nil },
|
168
|
+
{ key: :max_likes, value: nil }
|
169
|
+
] },
|
170
|
+
{ key: oct, values: [
|
171
|
+
{ key: :count, value: 1 },
|
172
|
+
{ key: :total_likes, value: 2 },
|
173
|
+
{ key: :mean_likes, value: '2.0' },
|
174
|
+
{ key: :min_likes, value: 2 },
|
175
|
+
{ key: :max_likes, value: 2 }
|
176
|
+
] },
|
177
|
+
{ key: nov, values: [
|
178
|
+
{ key: :count, value: 1 },
|
179
|
+
{ key: :total_likes, value: 3 },
|
180
|
+
{ key: :mean_likes, value: '3.0' },
|
181
|
+
{ key: :min_likes, value: 3 },
|
182
|
+
{ key: :max_likes, value: 3 }
|
183
|
+
] }
|
184
|
+
] },
|
185
|
+
{ key: joyce.name, values: [
|
186
|
+
{ key: nil, values: [
|
187
|
+
{ key: :count, value: 1 },
|
188
|
+
{ key: :total_likes, value: 3 },
|
189
|
+
{ key: :mean_likes, value: '3.0' },
|
190
|
+
{ key: :min_likes, value: 3 },
|
191
|
+
{ key: :max_likes, value: 3 }
|
192
|
+
] },
|
193
|
+
{ key: oct, values: [
|
194
|
+
{ key: :count, value: 2 },
|
195
|
+
{ key: :total_likes, value: 3 },
|
196
|
+
{ key: :mean_likes, value: '1.5' },
|
197
|
+
{ key: :min_likes, value: 1 },
|
198
|
+
{ key: :max_likes, value: 2 }
|
199
|
+
] },
|
200
|
+
{ key: nov, values: [
|
201
|
+
{ key: :count, value: 1 },
|
202
|
+
{ key: :total_likes, value: 1 },
|
203
|
+
{ key: :mean_likes, value: '1.0' },
|
204
|
+
{ key: :min_likes, value: 1 },
|
205
|
+
{ key: :max_likes, value: 1 }
|
206
|
+
] }
|
207
|
+
] },
|
208
|
+
{ key: woolf.name, values: [
|
209
|
+
{ key: nil, values: [
|
210
|
+
{ key: :count, value: 1 },
|
211
|
+
{ key: :total_likes, value: 3 },
|
212
|
+
{ key: :mean_likes, value: '3.0' },
|
213
|
+
{ key: :min_likes, value: 3 },
|
214
|
+
{ key: :max_likes, value: 3 }
|
215
|
+
] },
|
216
|
+
{ key: oct, values: [
|
217
|
+
{ key: :count, value: 1 },
|
218
|
+
{ key: :total_likes, value: 2 },
|
219
|
+
{ key: :mean_likes, value: '2.0' },
|
220
|
+
{ key: :min_likes, value: 2 },
|
221
|
+
{ key: :max_likes, value: 2 }
|
222
|
+
] },
|
223
|
+
{ key: nov, values: [
|
224
|
+
{ key: :count, value: 1 },
|
225
|
+
{ key: :total_likes, value: 3 },
|
226
|
+
{ key: :mean_likes, value: '3.0' },
|
227
|
+
{ key: :min_likes, value: 3 },
|
228
|
+
{ key: :max_likes, value: 3 }
|
229
|
+
] }
|
230
|
+
] }
|
231
|
+
]
|
232
|
+
end
|
233
|
+
|
234
|
+
specify 'sorting with nulls (1 grouper)' do
|
235
|
+
expect_equal data_by(:author, sort_desc: true), [
|
236
|
+
{ key: woolf.name, values: [
|
237
|
+
{ key: :count, value: 3 },
|
238
|
+
{ key: :total_likes, value: 8 },
|
239
|
+
{ key: :mean_likes, value: '2.6666666666666667' },
|
240
|
+
{ key: :min_likes, value: 2 },
|
241
|
+
{ key: :max_likes, value: 3 }
|
242
|
+
] },
|
243
|
+
{ key: joyce.name, values: [
|
244
|
+
{ key: :count, value: 4 },
|
245
|
+
{ key: :total_likes, value: 7 },
|
246
|
+
{ key: :mean_likes, value: '1.75' },
|
247
|
+
{ key: :min_likes, value: 1 },
|
248
|
+
{ key: :max_likes, value: 3 }
|
249
|
+
] },
|
250
|
+
{ key: nil, values: [
|
251
|
+
{key: :count, value: 2 },
|
252
|
+
{key: :total_likes, value: 5 },
|
253
|
+
{key: :mean_likes, value: '2.5' },
|
254
|
+
{key: :min_likes, value: 2 },
|
255
|
+
{key: :max_likes, value: 3 }
|
256
|
+
] }
|
257
|
+
]
|
258
|
+
|
259
|
+
expect_equal data_by(:published_at, bin_width: '1 month', sort_desc: true), [
|
260
|
+
{ key: nov, values: [
|
261
|
+
{ key: :count, value: 3 },
|
262
|
+
{ key: :total_likes, value: 7 },
|
263
|
+
{ key: :mean_likes, value: '2.3333333333333333' },
|
264
|
+
{ key: :min_likes, value: 1 },
|
265
|
+
{ key: :max_likes, value: 3 }
|
266
|
+
] },
|
267
|
+
{ key: oct, values: [
|
268
|
+
{ key: :count, value: 4 },
|
269
|
+
{ key: :total_likes, value: 7 },
|
270
|
+
{ key: :mean_likes, value: '1.75' },
|
271
|
+
{ key: :min_likes, value: 1 },
|
272
|
+
{ key: :max_likes, value: 2 }
|
273
|
+
] },
|
274
|
+
{ key: nil, values: [
|
275
|
+
{ key: :count, value: 2 },
|
276
|
+
{ key: :total_likes, value: 6 },
|
277
|
+
{ key: :mean_likes, value: '3.0' },
|
278
|
+
{ key: :min_likes, value: 3 },
|
279
|
+
{ key: :max_likes, value: 3 }
|
280
|
+
] }
|
281
|
+
]
|
282
|
+
|
283
|
+
if ActiveReporter.database_type == :postgres
|
284
|
+
expect_equal data_by(:author, nulls_last: true), [
|
285
|
+
{ key: joyce.name, values: [
|
286
|
+
{ key: :count, value: 4 },
|
287
|
+
{ key: :total_likes, value: 7 },
|
288
|
+
{ key: :mean_likes, value: '1.75' },
|
289
|
+
{ key: :min_likes, value: 1 },
|
290
|
+
{ key: :max_likes, value: 3 }
|
291
|
+
] },
|
292
|
+
{ key: woolf.name, values: [
|
293
|
+
{ key: :count, value: 3 },
|
294
|
+
{ key: :total_likes, value: 8 },
|
295
|
+
{ key: :mean_likes, value: '2.6666666666666667' },
|
296
|
+
{ key: :min_likes, value: 2 },
|
297
|
+
{ key: :max_likes, value: 3 }
|
298
|
+
] },
|
299
|
+
{ key: nil, values: [
|
300
|
+
{ key: :count, value: 2 },
|
301
|
+
{ key: :total_likes, value: 5 },
|
302
|
+
{ key: :mean_likes, value: '2.5' },
|
303
|
+
{ key: :min_likes, value: 2 },
|
304
|
+
{ key: :max_likes, value: 3 }
|
305
|
+
] }
|
306
|
+
]
|
307
|
+
|
308
|
+
expect_equal data_by(:author, sort_desc: true, nulls_last: true), [
|
309
|
+
{ key: nil, values: [
|
310
|
+
{ key: :count, value: 2 },
|
311
|
+
{ key: :total_likes, value: 5 },
|
312
|
+
{ key: :mean_likes, value: '2.5' },
|
313
|
+
{ key: :min_likes, value: 2 },
|
314
|
+
{ key: :max_likes, value: 3 }
|
315
|
+
] },
|
316
|
+
{ key: woolf.name, values: [
|
317
|
+
{ key: :count, value: 3 },
|
318
|
+
{ key: :total_likes, value: 8 },
|
319
|
+
{ key: :mean_likes, value: '2.6666666666666667' },
|
320
|
+
{ key: :min_likes, value: 2 },
|
321
|
+
{ key: :max_likes, value: 3 }
|
322
|
+
] },
|
323
|
+
{ key: joyce.name, values: [
|
324
|
+
{ key: :count, value: 4 },
|
325
|
+
{ key: :total_likes, value: 7 },
|
326
|
+
{ key: :mean_likes, value: '1.75' },
|
327
|
+
{ key: :min_likes, value: 1 },
|
328
|
+
{ key: :max_likes, value: 3 }
|
329
|
+
] }
|
330
|
+
]
|
331
|
+
|
332
|
+
expect_equal data_by(:published_at, bin_width: '1 month', nulls_last: true), [
|
333
|
+
{ key: oct, values: [
|
334
|
+
{ key: :count, value: 4 },
|
335
|
+
{ key: :total_likes, value: 7 },
|
336
|
+
{ key: :mean_likes, value: '1.75' },
|
337
|
+
{ key: :min_likes, value: 1 },
|
338
|
+
{ key: :max_likes, value: 2 }
|
339
|
+
] },
|
340
|
+
{ key: nov, values: [
|
341
|
+
{ key: :count, value: 3 },
|
342
|
+
{ key: :total_likes, value: 7 },
|
343
|
+
{ key: :mean_likes, value: '2.3333333333333333' },
|
344
|
+
{ key: :min_likes, value: 1 },
|
345
|
+
{ key: :max_likes, value: 3 }
|
346
|
+
] },
|
347
|
+
{ key: nil, values: [
|
348
|
+
{ key: :count, value: 2 },
|
349
|
+
{ key: :total_likes, value: 6 },
|
350
|
+
{ key: :mean_likes, value: '3.0' },
|
351
|
+
{ key: :min_likes, value: 3 },
|
352
|
+
{ key: :max_likes, value: 3 }
|
353
|
+
] }
|
354
|
+
]
|
355
|
+
|
356
|
+
expect_equal data_by(:published_at, bin_width: '1 month', sort_desc: true, nulls_last: true), [
|
357
|
+
{ key: nil, values: [
|
358
|
+
{ key: :count, value: 2 },
|
359
|
+
{ key: :total_likes, value: 6 },
|
360
|
+
{ key: :mean_likes, value: '3.0' },
|
361
|
+
{ key: :min_likes, value: 3 },
|
362
|
+
{ key: :max_likes, value: 3 }
|
363
|
+
] },
|
364
|
+
{ key: nov, values: [
|
365
|
+
{ key: :count, value: 3 },
|
366
|
+
{ key: :total_likes, value: 7 },
|
367
|
+
{ key: :mean_likes, value: '2.3333333333333333' },
|
368
|
+
{ key: :min_likes, value: 1 },
|
369
|
+
{ key: :max_likes, value: 3 }
|
370
|
+
] },
|
371
|
+
{ key: oct, values: [
|
372
|
+
{ key: :count, value: 4 },
|
373
|
+
{ key: :total_likes, value: 7 },
|
374
|
+
{ key: :mean_likes, value: '1.75' },
|
375
|
+
{ key: :min_likes, value: 1 },
|
376
|
+
{ key: :max_likes, value: 2 }
|
377
|
+
] }
|
378
|
+
]
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveReporter::Aggregator do
|
4
|
+
let(:report_model) do
|
5
|
+
Class.new(ActiveReporter::Report) do
|
6
|
+
report_on :Post
|
7
|
+
category_dimension :author, model: :author, attribute: :name, relation: ->(r) { r.left_outer_joins(:author) }
|
8
|
+
enum_dimension :status, attribute: :status
|
9
|
+
count_aggregator :count
|
10
|
+
sum_aggregator :total_likes, attribute: :likes
|
11
|
+
average_aggregator :mean_likes, attribute: :likes
|
12
|
+
min_aggregator :min_likes, attribute: :likes
|
13
|
+
max_aggregator :max_likes, attribute: :likes
|
14
|
+
array_aggregator :post_ids, attribute: :id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:report) { report_model.new(aggregators: aggregators, groupers: [:author, :status]) }
|
19
|
+
|
20
|
+
let!(:post_1) { create(:post, likes: 3, author: 'Alice') }
|
21
|
+
let!(:post_2) { create(:post, likes: 2, author: 'Alice') }
|
22
|
+
let!(:post_3) { create(:post, likes: 4, author: 'Bob') }
|
23
|
+
let!(:post_4) { create(:post, likes: 1, author: 'Bob') }
|
24
|
+
let!(:post_5) { create(:post, likes: 5, author: 'Bob') }
|
25
|
+
let!(:post_6) { create(:post, likes: 10, author: 'Chester') }
|
26
|
+
|
27
|
+
context 'aggregating post_ids' do
|
28
|
+
let(:aggregators) { :post_ids }
|
29
|
+
|
30
|
+
it 'should return post_ids values' do
|
31
|
+
if ActiveReporter.database_type == :postgres
|
32
|
+
expect(report.raw_data).to eq({
|
33
|
+
['Alice', 'published', 'post_ids'] => [post_1.id, post_2.id],
|
34
|
+
['Bob', 'published', 'post_ids'] => [post_3.id, post_4.id, post_5.id],
|
35
|
+
['Chester', 'published', 'post_ids'] => [post_6.id],
|
36
|
+
})
|
37
|
+
else
|
38
|
+
expect { report.raw_data }.to raise_error(ActiveReporter::InvalidParamsError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'aggregating max_likes' do
|
44
|
+
let(:aggregators) { :max_likes }
|
45
|
+
|
46
|
+
it 'should return max_likes values' do
|
47
|
+
expect(report.raw_data).to eq({
|
48
|
+
['Alice', 'published', 'max_likes'] => 3,
|
49
|
+
['Bob', 'published', 'max_likes'] => 5,
|
50
|
+
['Chester', 'published', 'max_likes'] => 10,
|
51
|
+
})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'aggregating min_likes' do
|
56
|
+
let(:aggregators) { :min_likes }
|
57
|
+
|
58
|
+
it 'should return min_likes values' do
|
59
|
+
expect(report.raw_data).to eq({
|
60
|
+
['Alice', 'published', 'min_likes'] => 2,
|
61
|
+
['Bob', 'published', 'min_likes'] => 1,
|
62
|
+
['Chester', 'published', 'min_likes'] => 10
|
63
|
+
})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'aggregating mean_likes' do
|
68
|
+
let(:aggregators) { :mean_likes }
|
69
|
+
|
70
|
+
it 'should return mean_likes values' do
|
71
|
+
expect(report.raw_data.collect{ |k,v| [k, v.round(2)] }.to_h).to eq({
|
72
|
+
['Alice', 'published', 'mean_likes'] => 2.50,
|
73
|
+
['Bob', 'published', 'mean_likes'] => 3.33,
|
74
|
+
['Chester', 'published', 'mean_likes'] => 10.00,
|
75
|
+
})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'aggregating total_likes' do
|
80
|
+
let(:aggregators) { :total_likes }
|
81
|
+
|
82
|
+
it 'should return total_likes values' do
|
83
|
+
expect(report.raw_data).to eq({
|
84
|
+
['Alice', 'published', 'total_likes'] => 5,
|
85
|
+
['Bob', 'published', 'total_likes'] => 10,
|
86
|
+
['Chester', 'published', 'total_likes'] => 10
|
87
|
+
})
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'aggregating count' do
|
92
|
+
let(:aggregators) { :count }
|
93
|
+
|
94
|
+
it 'should return count values' do
|
95
|
+
expect(report.raw_data).to eq({
|
96
|
+
['Alice', 'published', 'count'] => 2,
|
97
|
+
['Bob', 'published', 'count'] => 3,
|
98
|
+
['Chester', 'published', 'count'] => 1
|
99
|
+
})
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|