reports_kit 0.2.0 → 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/.rubocop.yml +2 -0
- data/.travis.yml +20 -0
- data/README.md +17 -19
- data/app/assets/javascripts/reports_kit/lib/_init.js +2 -1
- data/app/assets/javascripts/reports_kit/lib/chart.js +25 -16
- data/app/assets/javascripts/reports_kit/lib/report.js +42 -25
- data/app/assets/javascripts/reports_kit/lib/table.js +37 -2
- data/app/assets/stylesheets/reports_kit/reports.css.sass +3 -0
- data/docs/dimensions.md +26 -34
- data/docs/display_options.md +12 -15
- data/docs/filters.md +54 -63
- data/docs/measures.md +3 -4
- data/lib/reports_kit.rb +12 -10
- data/lib/reports_kit/base_controller.rb +1 -2
- data/lib/reports_kit/configuration.rb +19 -4
- data/lib/reports_kit/entity.rb +3 -0
- data/lib/reports_kit/helper.rb +17 -21
- data/lib/reports_kit/model_configuration.rb +1 -1
- data/lib/reports_kit/report_builder.rb +11 -11
- data/lib/reports_kit/reports/{abstract_measure.rb → abstract_series.rb} +1 -1
- data/lib/reports_kit/reports/{composite_measure.rb → composite_series.rb} +12 -8
- data/lib/reports_kit/reports/data/add_table_aggregations.rb +105 -0
- data/lib/reports_kit/reports/data/{composite_aggregation.rb → aggregate_composite.rb} +28 -27
- data/lib/reports_kit/reports/data/{one_dimension.rb → aggregate_one_dimension.rb} +9 -7
- data/lib/reports_kit/reports/data/{two_dimensions.rb → aggregate_two_dimensions.rb} +9 -8
- data/lib/reports_kit/reports/data/chart_options.rb +6 -11
- data/lib/reports_kit/reports/data/format_one_dimension.rb +56 -36
- data/lib/reports_kit/reports/data/format_table.rb +65 -0
- data/lib/reports_kit/reports/data/format_two_dimensions.rb +10 -8
- data/lib/reports_kit/reports/data/generate.rb +51 -28
- data/lib/reports_kit/reports/data/generate_for_properties.rb +52 -30
- data/lib/reports_kit/reports/data/populate_one_dimension.rb +30 -12
- data/lib/reports_kit/reports/data/populate_two_dimensions.rb +31 -31
- data/lib/reports_kit/reports/data/utils.rb +28 -24
- data/lib/reports_kit/reports/dimension.rb +4 -0
- data/lib/reports_kit/reports/{dimension_with_measure.rb → dimension_with_series.rb} +8 -9
- data/lib/reports_kit/reports/filter.rb +4 -0
- data/lib/reports_kit/reports/filter_types/base.rb +4 -3
- data/lib/reports_kit/reports/filter_types/boolean.rb +4 -4
- data/lib/reports_kit/reports/filter_types/datetime.rb +13 -3
- data/lib/reports_kit/reports/filter_types/number.rb +5 -5
- data/lib/reports_kit/reports/{filter_with_measure.rb → filter_with_series.rb} +7 -7
- data/lib/reports_kit/reports/generate_autocomplete_results.rb +2 -2
- data/lib/reports_kit/reports/inferrable_configuration.rb +6 -6
- data/lib/reports_kit/reports/{measure.rb → series.rb} +28 -15
- data/lib/reports_kit/reports_controller.rb +25 -5
- data/lib/reports_kit/value.rb +3 -0
- data/lib/reports_kit/version.rb +1 -1
- data/spec/fixtures/generate_inputs.yml +116 -63
- data/spec/fixtures/generate_outputs.yml +64 -0
- data/spec/reports_kit/report_builder_spec.rb +10 -12
- data/spec/reports_kit/reports/data/generate_spec.rb +559 -140
- data/spec/reports_kit/reports/{dimension_with_measure_spec.rb → dimension_with_series_spec.rb} +5 -7
- data/spec/reports_kit/reports/{filter_with_measure_spec.rb → filter_with_series_spec.rb} +3 -3
- data/spec/spec_helper.rb +5 -5
- data/spec/support/config.rb +31 -1
- data/spec/support/helpers.rb +6 -2
- metadata +17 -14
- data/lib/reports_kit/reports/data/entity.rb +0 -7
- data/lib/reports_kit/reports/data/value.rb +0 -7
@@ -2,12 +2,13 @@ module ReportsKit
|
|
2
2
|
module Reports
|
3
3
|
module Data
|
4
4
|
class FormatOneDimension
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :serieses_results, :serieses, :order, :limit
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
self.
|
9
|
-
self.
|
7
|
+
def initialize(serieses_results, order:, limit:)
|
8
|
+
self.serieses_results = serieses_results
|
9
|
+
self.serieses = serieses_results.keys
|
10
10
|
self.order = order
|
11
|
+
self.limit = limit
|
11
12
|
end
|
12
13
|
|
13
14
|
def perform
|
@@ -21,99 +22,118 @@ module ReportsKit
|
|
21
22
|
|
22
23
|
def entities
|
23
24
|
sorted_dimension_keys.map do |key|
|
24
|
-
Utils.dimension_key_to_entity(key,
|
25
|
+
Utils.dimension_key_to_entity(key, primary_dimension_with_series, dimension_ids_dimension_instances)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
29
|
def datasets
|
29
|
-
|
30
|
+
sorted_serieses_results.map do |series, result|
|
30
31
|
values = result.values.map do |raw_value|
|
31
|
-
Utils.raw_value_to_value(raw_value,
|
32
|
+
Utils.raw_value_to_value(raw_value, series.value_format_method)
|
32
33
|
end
|
33
34
|
{
|
34
|
-
entity:
|
35
|
+
entity: series,
|
35
36
|
values: values
|
36
37
|
}
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
def dimension_summaries
|
41
|
-
@dimension_summaries ||=
|
42
|
-
label = Utils.dimension_key_to_label(dimension_key,
|
42
|
+
@dimension_summaries ||= raw_dimension_keys.map do |dimension_key|
|
43
|
+
label = Utils.dimension_key_to_label(dimension_key, primary_dimension_with_series, dimension_ids_dimension_instances)
|
44
|
+
next if label.blank?
|
43
45
|
[dimension_key, label]
|
44
|
-
end
|
46
|
+
end.compact
|
45
47
|
end
|
46
48
|
|
47
49
|
def sorted_dimension_keys
|
48
|
-
|
50
|
+
sorted_serieses_results.first.last.keys
|
49
51
|
end
|
50
52
|
|
51
53
|
def dimension_keys_sorted_by_label
|
52
|
-
|
54
|
+
dimension_summaries.sort_by { |key, label| label.is_a?(String) ? label.downcase : label }.map(&:first)
|
53
55
|
end
|
54
56
|
|
55
57
|
def dimension_keys
|
56
|
-
|
58
|
+
dimension_summaries.map(&:first)
|
59
|
+
end
|
60
|
+
|
61
|
+
def raw_dimension_keys
|
62
|
+
serieses_results.first.last.keys
|
57
63
|
end
|
58
64
|
|
59
65
|
def dimension_ids_dimension_instances
|
60
66
|
@dimension_ids_dimension_instances ||= begin
|
61
|
-
dimension_ids =
|
62
|
-
Utils.dimension_to_dimension_ids_dimension_instances(
|
67
|
+
dimension_ids = raw_dimension_keys
|
68
|
+
Utils.dimension_to_dimension_ids_dimension_instances(primary_dimension_with_series, dimension_ids)
|
63
69
|
end
|
64
70
|
end
|
65
71
|
|
66
|
-
def
|
67
|
-
@
|
72
|
+
def primary_dimension_with_series
|
73
|
+
@primary_dimension_with_series ||= DimensionWithSeries.new(dimension: primary_series.dimensions.first, series: primary_series)
|
68
74
|
end
|
69
75
|
|
70
|
-
def
|
71
|
-
|
76
|
+
def primary_series
|
77
|
+
serieses.first
|
72
78
|
end
|
73
79
|
|
74
|
-
def
|
75
|
-
@
|
80
|
+
def sorted_serieses_results
|
81
|
+
@sorted_serieses_results ||= begin
|
76
82
|
if order.relation == 'dimension1' && order.field == 'label'
|
77
|
-
|
83
|
+
sorted_serieses_results = serieses_results.map do |series, dimension_keys_values|
|
84
|
+
dimension_keys_values = filter_dimension_keys_values(dimension_keys_values)
|
78
85
|
sorted_dimension_keys_values = dimension_keys_values.sort_by { |key, _| dimension_keys_sorted_by_label.index(key) }
|
79
86
|
sorted_dimension_keys_values = sorted_dimension_keys_values.reverse if order.direction == 'desc'
|
80
|
-
[
|
87
|
+
[series, Hash[sorted_dimension_keys_values]]
|
81
88
|
end
|
82
89
|
elsif (order.relation == 'dimension1' && order.field.nil?) || (order.relation == 0)
|
83
|
-
|
90
|
+
sorted_serieses_results = serieses_results.map do |series, dimension_keys_values|
|
91
|
+
dimension_keys_values = filter_dimension_keys_values(dimension_keys_values)
|
84
92
|
sorted_dimension_keys_values = dimension_keys_values.sort_by(&:first)
|
85
93
|
sorted_dimension_keys_values = sorted_dimension_keys_values.reverse if order.direction == 'desc'
|
86
|
-
[
|
94
|
+
[series, Hash[sorted_dimension_keys_values]]
|
87
95
|
end
|
88
96
|
elsif order.relation.is_a?(Fixnum)
|
89
|
-
|
90
|
-
raise ArgumentError.new("Invalid order column: #{order.relation}") unless
|
91
|
-
dimension_keys_values =
|
97
|
+
series_index = order.relation - 1
|
98
|
+
raise ArgumentError.new("Invalid order column: #{order.relation}") unless series_index.in?((0..(serieses_results.length - 1)))
|
99
|
+
dimension_keys_values = serieses_results.values.to_a[series_index]
|
92
100
|
sorted_dimension_keys = dimension_keys_values.sort_by(&:last).map(&:first)
|
93
101
|
sorted_dimension_keys = sorted_dimension_keys.reverse if order.direction == 'desc'
|
94
|
-
|
102
|
+
sorted_serieses_results = serieses_results.map do |series, dimension_keys_values|
|
103
|
+
dimension_keys_values = filter_dimension_keys_values(dimension_keys_values)
|
95
104
|
dimension_keys_values = dimension_keys_values.sort_by { |dimension_key, _| sorted_dimension_keys.index(dimension_key) }
|
96
|
-
[
|
105
|
+
[series, Hash[dimension_keys_values]]
|
97
106
|
end
|
98
107
|
elsif order.relation == 'count'
|
99
108
|
dimension_keys_sums = Hash.new(0)
|
100
|
-
|
109
|
+
serieses_results.values.each do |dimension_keys_values|
|
110
|
+
dimension_keys_values = filter_dimension_keys_values(dimension_keys_values)
|
101
111
|
dimension_keys_values.each do |dimension_key, value|
|
102
112
|
dimension_keys_sums[dimension_key] += value
|
103
113
|
end
|
104
114
|
end
|
105
115
|
sorted_dimension_keys = dimension_keys_sums.sort_by(&:last).map(&:first)
|
106
116
|
sorted_dimension_keys = sorted_dimension_keys.reverse if order.direction == 'desc'
|
107
|
-
|
117
|
+
sorted_serieses_results = serieses_results.map do |series, dimension_keys_values|
|
118
|
+
dimension_keys_values = filter_dimension_keys_values(dimension_keys_values)
|
108
119
|
dimension_keys_values = dimension_keys_values.sort_by { |dimension_key, _| sorted_dimension_keys.index(dimension_key) }
|
109
|
-
[
|
120
|
+
[series, Hash[dimension_keys_values]]
|
110
121
|
end
|
111
122
|
else
|
112
|
-
|
123
|
+
sorted_serieses_results = serieses_results
|
113
124
|
end
|
114
|
-
|
125
|
+
if limit
|
126
|
+
sorted_serieses_results = sorted_serieses_results.map do |series, results|
|
127
|
+
[series, Hash[results.to_a.take(limit)]]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
Hash[sorted_serieses_results]
|
115
131
|
end
|
116
132
|
end
|
133
|
+
|
134
|
+
def filter_dimension_keys_values(dimension_keys_values)
|
135
|
+
dimension_keys_values.select { |key, values| dimension_keys.include?(key) }
|
136
|
+
end
|
117
137
|
end
|
118
138
|
end
|
119
139
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ReportsKit
|
2
|
+
module Reports
|
3
|
+
module Data
|
4
|
+
class FormatTable
|
5
|
+
attr_accessor :data, :format, :first_column_label, :report_options
|
6
|
+
|
7
|
+
VALID_AGGREGATION_OPERATORS = [:sum]
|
8
|
+
|
9
|
+
def initialize(data, format:, first_column_label:, report_options:)
|
10
|
+
self.data = data
|
11
|
+
self.format = format
|
12
|
+
self.first_column_label = first_column_label
|
13
|
+
self.report_options = report_options || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def perform
|
17
|
+
table_data
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def table_data
|
23
|
+
data_rows_with_labels = data_rows.map.with_index do |data_row, index|
|
24
|
+
label = format_string(data[:labels][index])
|
25
|
+
[label] + data_row
|
26
|
+
end
|
27
|
+
[column_names] + data_rows_with_labels
|
28
|
+
end
|
29
|
+
|
30
|
+
def column_names
|
31
|
+
column_names_column_values[0]
|
32
|
+
end
|
33
|
+
|
34
|
+
def column_values
|
35
|
+
column_names_column_values[1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def data_rows
|
39
|
+
@data_rows ||= column_values.transpose
|
40
|
+
end
|
41
|
+
|
42
|
+
def column_names_column_values
|
43
|
+
@column_names_column_values ||= begin
|
44
|
+
column_names = [format_string(first_column_label)]
|
45
|
+
column_values = []
|
46
|
+
data[:datasets].each do |dataset|
|
47
|
+
column_names << format_string(dataset[:label])
|
48
|
+
column_values << dataset[:data]
|
49
|
+
end
|
50
|
+
[column_names, column_values]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def format_string(string)
|
55
|
+
return string unless string && strip_html_tags?
|
56
|
+
ActionView::Base.full_sanitizer.sanitize(string)
|
57
|
+
end
|
58
|
+
|
59
|
+
def strip_html_tags?
|
60
|
+
format == 'csv'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -2,14 +2,15 @@ module ReportsKit
|
|
2
2
|
module Reports
|
3
3
|
module Data
|
4
4
|
class FormatTwoDimensions
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :series, :dimension, :second_dimension, :dimension_keys_values, :order, :limit
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
self.
|
9
|
-
self.dimension =
|
10
|
-
self.second_dimension =
|
7
|
+
def initialize(series, dimension_keys_values, order:, limit:)
|
8
|
+
self.series = series
|
9
|
+
self.dimension = series.dimensions[0]
|
10
|
+
self.second_dimension = series.dimensions[1]
|
11
11
|
self.dimension_keys_values = dimension_keys_values
|
12
12
|
self.order = order
|
13
|
+
self.limit = limit
|
13
14
|
end
|
14
15
|
|
15
16
|
def perform
|
@@ -33,7 +34,7 @@ module ReportsKit
|
|
33
34
|
primary_keys_secondary_keys_values[primary_key][secondary_key]
|
34
35
|
end
|
35
36
|
values = raw_values.map do |raw_value|
|
36
|
-
Utils.raw_value_to_value(raw_value,
|
37
|
+
Utils.raw_value_to_value(raw_value, series.value_format_method)
|
37
38
|
end
|
38
39
|
[secondary_key, values]
|
39
40
|
end
|
@@ -120,12 +121,13 @@ module ReportsKit
|
|
120
121
|
def primary_summaries
|
121
122
|
primary_keys.map do |key|
|
122
123
|
label = Utils.dimension_key_to_label(key, dimension, dimension_ids_dimension_instances)
|
124
|
+
next if label.blank?
|
123
125
|
[key, label]
|
124
|
-
end
|
126
|
+
end.compact
|
125
127
|
end
|
126
128
|
|
127
129
|
def primary_dimension_keys_sorted_by_label
|
128
|
-
@primary_dimension_keys_sorted_by_label ||= primary_summaries.sort_by(
|
130
|
+
@primary_dimension_keys_sorted_by_label ||= primary_summaries.sort_by { |key, label| label.is_a?(String) ? label.downcase : label }.map(&:first)
|
129
131
|
end
|
130
132
|
|
131
133
|
def primary_keys
|
@@ -8,28 +8,30 @@ module ReportsKit
|
|
8
8
|
|
9
9
|
def initialize(properties, context_record: nil)
|
10
10
|
self.properties = properties.deep_symbolize_keys
|
11
|
+
self.properties = ReportsKit.configuration.default_properties.deep_merge(self.properties) if ReportsKit.configuration.default_properties
|
11
12
|
self.properties = Utils.normalize_properties(self.properties)
|
12
13
|
self.context_record = context_record
|
13
14
|
end
|
14
15
|
|
15
16
|
def perform
|
16
17
|
data = ReportsKit::Cache.get(properties, context_record)
|
17
|
-
return data if data
|
18
|
+
return data.deep_symbolize_keys if data
|
18
19
|
|
19
20
|
if two_dimensions?
|
20
|
-
raw_data = Data::FormatTwoDimensions.new(
|
21
|
+
raw_data = Data::FormatTwoDimensions.new(serieses.first, serieses_results.first.last, order: order, limit: limit).perform
|
21
22
|
else
|
22
|
-
raw_data = Data::FormatOneDimension.new(
|
23
|
+
raw_data = Data::FormatOneDimension.new(serieses_results, order: order, limit: limit).perform
|
23
24
|
end
|
24
|
-
raw_data =
|
25
|
+
raw_data = format_csv_times(raw_data) if format == 'csv'
|
26
|
+
raw_data = Data::AddTableAggregations.new(raw_data, report_options: report_options).perform if table_or_csv?
|
27
|
+
raw_data = data_format_method.call(data: raw_data, properties: properties, context_record: context_record) if data_format_method
|
28
|
+
raw_data = csv_data_format_method.call(data: raw_data, properties: properties, context_record: context_record) if csv_data_format_method && format == 'csv'
|
25
29
|
chart_data = format_chart_data(raw_data)
|
26
30
|
|
27
31
|
data = { chart_data: chart_data }
|
28
32
|
data = ChartOptions.new(data, options: properties[:chart], inferred_options: inferred_options).perform
|
29
|
-
|
30
|
-
|
31
|
-
data[:type] = format
|
32
|
-
end
|
33
|
+
data[:report_options] = report_options if report_options
|
34
|
+
data = format_table_data(data) if table_or_csv?
|
33
35
|
ReportsKit::Cache.set(properties, context_record, data)
|
34
36
|
data
|
35
37
|
end
|
@@ -48,12 +50,23 @@ module ReportsKit
|
|
48
50
|
chart_data
|
49
51
|
end
|
50
52
|
|
51
|
-
def
|
52
|
-
|
53
|
+
def format_table_data(data)
|
54
|
+
data[:table_data] = Data::FormatTable.new(
|
55
|
+
data.delete(:chart_data),
|
56
|
+
format: format,
|
57
|
+
first_column_label: primary_dimension.label,
|
58
|
+
report_options: report_options
|
59
|
+
).perform
|
60
|
+
data[:type] = format
|
61
|
+
data
|
62
|
+
end
|
63
|
+
|
64
|
+
def serieses_results
|
65
|
+
@serieses_results ||= GenerateForProperties.new(properties, context_record: context_record).perform
|
53
66
|
end
|
54
67
|
|
55
68
|
def two_dimensions?
|
56
|
-
dimension_keys =
|
69
|
+
dimension_keys = serieses_results.first.last.keys
|
57
70
|
dimension_keys.first.is_a?(Array)
|
58
71
|
end
|
59
72
|
|
@@ -64,46 +77,56 @@ module ReportsKit
|
|
64
77
|
end
|
65
78
|
end
|
66
79
|
|
80
|
+
def limit
|
81
|
+
properties[:limit]
|
82
|
+
end
|
83
|
+
|
67
84
|
def inferred_order
|
68
85
|
return Order.new('dimension1', nil, 'asc') if primary_dimension.configured_by_time?
|
69
86
|
Order.new('count', nil, 'desc')
|
70
87
|
end
|
71
88
|
|
72
|
-
def
|
73
|
-
@
|
89
|
+
def serieses
|
90
|
+
@serieses ||= Series.new_from_properties!(properties, context_record: context_record)
|
91
|
+
end
|
92
|
+
|
93
|
+
def report_options
|
94
|
+
properties[:report_options]
|
74
95
|
end
|
75
96
|
|
76
97
|
def data_format_method
|
77
|
-
ReportsKit.configuration.custom_method(
|
98
|
+
ReportsKit.configuration.custom_method(report_options.try(:[], :data_format_method))
|
99
|
+
end
|
100
|
+
|
101
|
+
def csv_data_format_method
|
102
|
+
ReportsKit.configuration.custom_method(report_options.try(:[], :csv_data_format_method))
|
78
103
|
end
|
79
104
|
|
80
105
|
def format
|
81
106
|
properties[:format]
|
82
107
|
end
|
83
108
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
column_values << dataset[:data]
|
109
|
+
def format_csv_times(raw_data)
|
110
|
+
return raw_data unless primary_dimension.configured_by_time?
|
111
|
+
raw_data[:entities] = raw_data[:entities].map do |entity|
|
112
|
+
entity.label = Utils.format_csv_time(entity.instance)
|
113
|
+
entity
|
90
114
|
end
|
91
|
-
|
92
|
-
rows = rows.map.with_index do |row, index|
|
93
|
-
label = data[:labels][index]
|
94
|
-
row.unshift(label)
|
95
|
-
end
|
96
|
-
[column_names] + rows
|
115
|
+
raw_data
|
97
116
|
end
|
98
117
|
|
99
118
|
def primary_dimension
|
100
|
-
|
119
|
+
serieses.first.dimensions.first
|
120
|
+
end
|
121
|
+
|
122
|
+
def table_or_csv?
|
123
|
+
format.in?(%w(table csv))
|
101
124
|
end
|
102
125
|
|
103
126
|
def inferred_options
|
104
127
|
{
|
105
128
|
x_axis_label: primary_dimension.label,
|
106
|
-
y_axis_label:
|
129
|
+
y_axis_label: serieses.length == 1 ? serieses.first.label : nil
|
107
130
|
}
|
108
131
|
end
|
109
132
|
end
|
@@ -13,23 +13,23 @@ module ReportsKit
|
|
13
13
|
|
14
14
|
def perform
|
15
15
|
if composite_operator
|
16
|
-
raise ArgumentError.new('Aggregations require at least one
|
17
|
-
dimension_keys_values = Data::
|
18
|
-
|
19
|
-
elsif
|
20
|
-
dimension_keys_values = Data::
|
21
|
-
|
22
|
-
elsif
|
23
|
-
dimension_keys_values = Data::
|
24
|
-
|
25
|
-
|
26
|
-
elsif
|
27
|
-
|
16
|
+
raise ArgumentError.new('Aggregations require at least one series') if all_serieses.length == 0
|
17
|
+
dimension_keys_values = Data::AggregateComposite.new(properties, context_record: context_record).perform
|
18
|
+
serieses_dimension_keys_values = { CompositeSeries.new(properties) => dimension_keys_values }
|
19
|
+
elsif all_serieses.length == 1 && composite_serieses.length == 1
|
20
|
+
dimension_keys_values = Data::AggregateComposite.new(composite_serieses.first.properties, context_record: context_record).perform
|
21
|
+
serieses_dimension_keys_values = { all_serieses.first => dimension_keys_values }
|
22
|
+
elsif all_serieses.length == 1 && all_serieses.first.dimensions.length == 2
|
23
|
+
dimension_keys_values = Data::AggregateTwoDimensions.new(all_serieses.first).perform
|
24
|
+
serieses_dimension_keys_values = { all_serieses.first => dimension_keys_values }
|
25
|
+
serieses_dimension_keys_values = Data::PopulateTwoDimensions.new(serieses_dimension_keys_values).perform
|
26
|
+
elsif all_serieses.length > 0
|
27
|
+
serieses_dimension_keys_values = serieses_dimension_keys_values_for_one_dimension
|
28
28
|
else
|
29
29
|
raise ArgumentError.new('The configuration of measurse and dimensions is invalid')
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
serieses_dimension_keys_values
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
@@ -42,32 +42,54 @@ module ReportsKit
|
|
42
42
|
properties[:name]
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
|
47
|
-
raise ArgumentError.new('When more than one
|
45
|
+
def serieses_dimension_keys_values_for_one_dimension
|
46
|
+
multi_dimension_serieses_exist = all_serieses.any? { |series| series.dimensions.length > 1 }
|
47
|
+
raise ArgumentError.new('When more than one series are configured, only one dimension may be used per series') if multi_dimension_serieses_exist
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
if all_serieses.length > 1 && ReportsKit.configuration.use_concurrent_queries
|
50
|
+
serieses_dimension_keys_values = multithreaded_serieses_dimension_keys_values
|
51
|
+
else
|
52
|
+
serieses_dimension_keys_values = all_serieses.map do |series|
|
53
|
+
[series, dimension_keys_values_for_series(series)]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
serieses_dimension_keys_values = Hash[serieses_dimension_keys_values]
|
57
|
+
Data::PopulateOneDimension.new(serieses_dimension_keys_values, context_record: context_record, properties: properties).perform
|
58
|
+
end
|
59
|
+
|
60
|
+
def multithreaded_serieses_dimension_keys_values
|
61
|
+
threads = all_serieses.map do |series|
|
62
|
+
Thread.new do
|
63
|
+
ActiveRecord::Base.connection_pool.with_connection do
|
64
|
+
begin
|
65
|
+
[series, dimension_keys_values_for_series(series)]
|
66
|
+
ensure
|
67
|
+
ActiveRecord::Base.connection.close if ActiveRecord::Base.connection
|
68
|
+
end
|
69
|
+
end
|
54
70
|
end
|
55
|
-
[measure, dimension_keys_values]
|
56
71
|
end
|
57
|
-
|
58
|
-
|
72
|
+
threads.map(&:join).map(&:value)
|
73
|
+
end
|
74
|
+
|
75
|
+
def dimension_keys_values_for_series(series)
|
76
|
+
if series.is_a?(CompositeSeries)
|
77
|
+
Data::AggregateComposite.new(series.properties, context_record: context_record).perform
|
78
|
+
else
|
79
|
+
Data::AggregateOneDimension.new(series).perform
|
80
|
+
end
|
59
81
|
end
|
60
82
|
|
61
|
-
def
|
62
|
-
@
|
83
|
+
def all_serieses
|
84
|
+
@all_serieses ||= Series.new_from_properties!(properties, context_record: context_record)
|
63
85
|
end
|
64
86
|
|
65
|
-
def
|
66
|
-
@
|
87
|
+
def composite_serieses
|
88
|
+
@composite_serieses ||= all_serieses.grep(CompositeSeries)
|
67
89
|
end
|
68
90
|
|
69
|
-
def
|
70
|
-
@
|
91
|
+
def serieses
|
92
|
+
@serieses ||= all_serieses.grep(Series)
|
71
93
|
end
|
72
94
|
end
|
73
95
|
end
|