simple_drilldown 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -6
- data/app/views/drilldown/_chart.html.erb +1 -1
- data/app/views/drilldown/_field.html.erb +0 -1
- data/app/views/drilldown/_filter.html.erb +4 -13
- data/app/views/drilldown/_record_list.html.erb +3 -3
- data/app/views/drilldown/_row.html.erb +9 -9
- data/app/views/drilldown/_summary_table.html.erb +2 -2
- data/app/views/drilldown/excel_export_transactions.builder +1 -1
- data/lib/generators/drilldown_controller/drilldown_controller_generator.rb +2 -1
- data/lib/generators/drilldown_controller/templates/drilldown_controller.rb.erb +14 -5
- data/lib/generators/drilldown_controller/templates/drilldown_controller_test.rb.erb +15 -0
- data/lib/simple_drilldown/drilldown_controller.rb +64 -67
- data/lib/simple_drilldown/engine.rb +3 -0
- data/lib/simple_drilldown/routing.rb +1 -0
- data/lib/simple_drilldown/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9994fb706e46554bec7e26a9191cdc10e2675a19770e4414019f5b4a067e7daf
|
4
|
+
data.tar.gz: 874f30d58de361193d6faed89b2af82e8899b0c628861865b917af9466faa64d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61559d0c5e2f91474c86bbb3424c55e41d4fb355921a06cd3b4627ea1ab72a789be74989e53135b7179ea3b59feec83d140ed4e681fb85f111f0f024017a169d
|
7
|
+
data.tar.gz: 8bed5fd23fb6254bf5280ddce378738294af1bf5de119da11000695a3c594e48797b9f820987ef4296ed94ac6a680075f20924a6d6473702f7b05c7fe120af34
|
data/README.md
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
<img align="right" src="https://travis-ci.org/DatekWireless/simple_drilldown.svg?branch=master" alt="Build Status">
|
5
5
|
</a>
|
6
6
|
|
7
|
-
simple_drilldown offers a simple way to define axis to filter and group records
|
7
|
+
`simple_drilldown` offers a simple way to define axis to filter and group records
|
8
8
|
for analysis. The result is a record count for the selected filter and
|
9
|
-
distribution and the option to list the actual records.
|
9
|
+
distribution and the option to list and export the actual records.
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
@@ -16,6 +16,10 @@ For a given schema:
|
|
16
16
|
|
17
17
|
```ruby
|
18
18
|
ActiveRecord::Schema.define(version: 20141204155251) do
|
19
|
+
create_table "users" do |t|
|
20
|
+
t.string "name", limit: 16, null: false
|
21
|
+
end
|
22
|
+
|
19
23
|
create_table "posts" do |t|
|
20
24
|
t.string "title", null: false
|
21
25
|
t.text "body", null: false
|
@@ -25,12 +29,9 @@ ActiveRecord::Schema.define(version: 20141204155251) do
|
|
25
29
|
t.datetime "updated_at", null: false
|
26
30
|
end
|
27
31
|
|
28
|
-
create_table "users" do |t|
|
29
|
-
t.string "name", limit: 16, null: false
|
30
|
-
end
|
31
|
-
|
32
32
|
create_table "comments" do |t|
|
33
33
|
t.integer "post_id", null: false
|
34
|
+
t.integer "user_id", null: false
|
34
35
|
t.string "title", null: false
|
35
36
|
t.text "body", null: false
|
36
37
|
t.integer "rating", null: false
|
@@ -65,6 +66,8 @@ end
|
|
65
66
|
Create a new controller to focus on posts. Each drilldown controller focuses on
|
66
67
|
one main entity.
|
67
68
|
|
69
|
+
bin/rails g drilldown_controller User
|
70
|
+
|
68
71
|
```ruby
|
69
72
|
class PostsDrilldownController < DrilldownController
|
70
73
|
|
@@ -37,7 +37,7 @@
|
|
37
37
|
<% (0..2).each do |i|
|
38
38
|
options = [['', '']]
|
39
39
|
options << [@dimensions[i][:pretty_name], @dimensions[i][:url_param_name]] if @dimensions[i]
|
40
|
-
options += @remaining_dimensions.keys.map { |name| [
|
40
|
+
options += @remaining_dimensions.keys.map { |name| [controller.c_dimension_defs[name][:pretty_name], name] } %>
|
41
41
|
<%= t(i == 0 ? :group_by : :then_by) %>:
|
42
42
|
<%= form.select 'dimensions', options, { :selected => @search.dimensions && @search.dimensions[i] },
|
43
43
|
{ :onChange => 'form.submit()', :name => 'search[dimensions][]', :id => "search_dimensions_#{i}" } %>
|
@@ -4,17 +4,8 @@
|
|
4
4
|
</div>
|
5
5
|
|
6
6
|
<% choices = Concurrent::Hash.new %>
|
7
|
-
<%
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
<% choices[dimension_name] = [[t(:all), nil]] + (dimension[:legal_values] && dimension[:legal_values].call(@search).map { |o| o.is_a?(Array) ? [o[0].to_s, o[1].to_s] : o.to_s } || []) %>
|
12
|
-
<% end %>
|
13
|
-
<% end %>
|
14
|
-
<% next [t, dimension_name] %>
|
15
|
-
<% end %>
|
16
|
-
<% threads.each do |t, dimension_name| %>
|
17
|
-
<% t.join %>
|
18
|
-
<%= render partial: 'drilldown/field', locals: {choices: choices[dimension_name] || [],
|
19
|
-
form: form, dimension_name: dimension_name} %>
|
7
|
+
<% controller.c_dimension_defs.each do |dimension_name, dimension| %>
|
8
|
+
<% choices[dimension_name] = [[t(:all), nil]] + (dimension[:legal_values] && dimension[:legal_values].call(@search).map { |o| o.is_a?(Array) ? [o[0].to_s, o[1].to_s] : o.to_s } || []) %>
|
9
|
+
<%= render partial: 'drilldown/field', locals: { choices: choices[dimension_name] || [],
|
10
|
+
form: form, dimension_name: dimension_name } %>
|
20
11
|
<% end %>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<% unless result[:transactions].empty? %>
|
2
2
|
<tr>
|
3
|
-
<td colspan="
|
3
|
+
<td colspan="<%= controller.c_summary_fields.size + 1 %>">
|
4
4
|
<table class="table table-condensed table-bordered" style="padding-bottom: 10px;">
|
5
|
-
<%=render :partial => '/drilldown/row_header' %>
|
5
|
+
<%= render :partial => '/drilldown/row_header' %>
|
6
6
|
<% result[:transactions].each do |t| %>
|
7
|
-
<%=render :partial => '/drilldown/row', :locals => {:transaction => t, :previous_transaction => nil, :errors => [], :error_row => false, :meter1_errors => false} %>
|
7
|
+
<%= render :partial => '/drilldown/row', :locals => { :transaction => t, :previous_transaction => nil, :errors => [], :error_row => false, :meter1_errors => false } %>
|
8
8
|
<% end %>
|
9
9
|
</table>
|
10
10
|
</td>
|
@@ -1,13 +1,13 @@
|
|
1
1
|
<tr valign="top">
|
2
2
|
<% @search.fields.each do |field| %>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
<td>
|
4
|
+
<% if field == 'time' %>
|
5
|
+
<%= (transaction.respond_to?(:completed_at) ? transaction.completed_at : transaction.created_at).localtime.strftime('%Y-%m-%d %H:%M') %>
|
6
|
+
<% else %>
|
7
|
+
<% field_def = controller.c_fields[field.to_sym] %>
|
8
|
+
<%= field_def[:attr_method] ? field_def[:attr_method].call(transaction) : transaction.send(field) %>
|
9
|
+
<% end %>
|
10
|
+
</td>
|
11
11
|
<% end %>
|
12
|
-
<td><%=
|
12
|
+
<td><%= link_to t(:show), transaction %></td>
|
13
13
|
</tr>
|
@@ -3,8 +3,8 @@
|
|
3
3
|
<% @dimensions.each do |d| %>
|
4
4
|
<th><%=h d[:pretty_name]%></th>
|
5
5
|
<% end %>
|
6
|
-
<th><%= t
|
7
|
-
<%=
|
6
|
+
<th><%= t controller.c_target_class.table_name.capitalize %></th>
|
7
|
+
<%= controller.c_summary_fields.map{|l| "<th>#{t(l)}</th>"}.join("\n").html_safe %>
|
8
8
|
</tr>
|
9
9
|
|
10
10
|
<%=summary_row(@result) %>
|
@@ -45,7 +45,7 @@ xml.Workbook(
|
|
45
45
|
@transactions.each do |transaction|
|
46
46
|
xml.Row do
|
47
47
|
@transaction_fields.each do |field|
|
48
|
-
field_map =
|
48
|
+
field_map = controller.c_fields[field.to_sym]
|
49
49
|
if field == 'time'
|
50
50
|
xml.Cell 'ss:StyleID' => 'DateOnlyFormat' do
|
51
51
|
xml.Data transaction.completed_at.gmtime.xmlschema, 'ss:Type' => 'DateTime'
|
@@ -5,6 +5,7 @@ class DrilldownControllerGenerator < Rails::Generators::NamedBase
|
|
5
5
|
|
6
6
|
def copy_drilldown_controller_file
|
7
7
|
template 'drilldown_controller.rb.erb', "app/controllers/#{file_name}_drilldown_controller.rb"
|
8
|
-
|
8
|
+
template 'drilldown_controller_test.rb.erb', "test/controllers/#{file_name}_drilldown_controller_test.rb"
|
9
|
+
route "draw_drilldown :#{singular_name}_drilldown"
|
9
10
|
end
|
10
11
|
end
|
@@ -1,14 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# What fields should be displayed as default when listing actual <%= class_name %> records.
|
5
|
-
default_fields %w[created_at updated_at] # TODO(uwe): Read fields from schema?
|
3
|
+
require 'simple_drilldown/drilldown_controller'
|
6
4
|
|
5
|
+
class <%= class_name %>DrilldownController < SimpleDrilldown::DrilldownController
|
7
6
|
# The main focus of the drilldown
|
8
|
-
target_class <%= class_name %>
|
7
|
+
# target_class <%= class_name %>
|
8
|
+
|
9
|
+
# `where` clause for the base line
|
10
|
+
# base_condition '1=1'
|
9
11
|
|
10
12
|
# How should we count the reords?
|
11
|
-
select 'count(*) as count'
|
13
|
+
# select 'count(*) as count'
|
14
|
+
|
15
|
+
# When selecting records, what relations should be included for optimization?
|
16
|
+
# Other relations can be included for specific dimensions and fields.
|
17
|
+
# base_includes :user, :comments # TODO(uwe): Read relations from schema?
|
18
|
+
|
19
|
+
# What fields should be displayed as default when listing actual <%= class_name %> records.
|
20
|
+
default_fields %w[created_at updated_at] # TODO(uwe): Read fields from schema?
|
12
21
|
|
13
22
|
# When listing records, what relations should be included for optimization?
|
14
23
|
# list_includes :user, :comments # TODO(uwe): Read relations from schema?
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class <%= class_name %>DrilldownControllerTest < ActionDispatch::IntegrationTest
|
6
|
+
test 'should get index' do
|
7
|
+
get <%= singular_name %>_drilldown_url
|
8
|
+
assert_response :success
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'should get index with list' do
|
12
|
+
get <%= singular_name %>_drilldown_url search: { list: 1 }
|
13
|
+
assert_response :success
|
14
|
+
end
|
15
|
+
end
|
@@ -9,46 +9,63 @@ module SimpleDrilldown
|
|
9
9
|
|
10
10
|
LIST_LIMIT = 10_000
|
11
11
|
|
12
|
+
class_attribute :c_base_condition, default: '1=1'
|
13
|
+
class_attribute :c_base_group, default: []
|
14
|
+
class_attribute :c_base_includes, default: []
|
15
|
+
class_attribute :c_default_fields, default: []
|
16
|
+
class_attribute :c_default_select_value, default: SimpleDrilldown::Search::SelectValue::COUNT
|
17
|
+
class_attribute :c_dimension_defs, default: Concurrent::Hash.new
|
18
|
+
class_attribute :c_fields, default: {}
|
19
|
+
class_attribute :c_list_includes, default: []
|
20
|
+
class_attribute :c_list_order
|
21
|
+
class_attribute :c_select, default: 'count(*) as count'
|
22
|
+
class_attribute :c_summary_fields, default: []
|
23
|
+
class_attribute :c_target_class
|
24
|
+
|
12
25
|
class << self
|
26
|
+
def inherited(base)
|
27
|
+
super
|
28
|
+
base.c_target_class = base.name.chomp('DrilldownController').constantize
|
29
|
+
end
|
30
|
+
|
13
31
|
def base_condition(base_condition)
|
14
|
-
|
32
|
+
self.c_base_condition = base_condition
|
15
33
|
end
|
16
34
|
|
17
35
|
def base_includes(base_includes)
|
18
|
-
|
36
|
+
self.c_base_includes = base_includes
|
19
37
|
end
|
20
38
|
|
21
39
|
def base_group(base_group)
|
22
|
-
|
40
|
+
self.c_base_group = base_group
|
23
41
|
end
|
24
42
|
|
25
|
-
def default_fields(
|
26
|
-
|
43
|
+
def default_fields(default_fields)
|
44
|
+
self.c_default_fields = default_fields
|
27
45
|
end
|
28
46
|
|
29
47
|
def target_class(target_class)
|
30
|
-
|
48
|
+
self.c_target_class = target_class
|
31
49
|
end
|
32
50
|
|
33
51
|
def select(select)
|
34
|
-
|
52
|
+
self.c_select = select
|
35
53
|
end
|
36
54
|
|
37
55
|
def list_includes(list_includes)
|
38
|
-
|
56
|
+
self.c_list_includes = list_includes
|
39
57
|
end
|
40
58
|
|
41
59
|
def list_order(list_order)
|
42
|
-
|
60
|
+
self.c_list_order = list_order
|
43
61
|
end
|
44
62
|
|
45
63
|
def field(name, **options)
|
46
|
-
|
47
|
-
@@fields[name] = options
|
64
|
+
c_fields[name] = options
|
48
65
|
end
|
49
66
|
|
50
67
|
def summary_fields(*summary_fields)
|
51
|
-
|
68
|
+
self.c_summary_fields = summary_fields
|
52
69
|
end
|
53
70
|
|
54
71
|
def dimension(name, select_expression = name, options = {})
|
@@ -74,9 +91,7 @@ module SimpleDrilldown
|
|
74
91
|
raise "Unknown options: #{query_opts.keys.inspect}" unless (query_opts.keys - %i[select includes where]).empty?
|
75
92
|
end
|
76
93
|
|
77
|
-
|
78
|
-
|
79
|
-
@@dimension_defs[name.to_s] = {
|
94
|
+
c_dimension_defs[name.to_s] = {
|
80
95
|
includes: queries.inject([]) do |a, e|
|
81
96
|
i = e[:includes]
|
82
97
|
next a unless i
|
@@ -101,7 +116,7 @@ module SimpleDrilldown
|
|
101
116
|
my_filter = search.filter.dup
|
102
117
|
my_filter.delete(field.to_s) unless preserve_filter
|
103
118
|
filter_conditions, _t, includes = make_conditions(my_filter)
|
104
|
-
dimension_def =
|
119
|
+
dimension_def = c_dimension_defs[field.to_s]
|
105
120
|
result_sets = dimension_def[:queries].map do |query|
|
106
121
|
if query[:includes]
|
107
122
|
if query[:includes].is_a?(Array)
|
@@ -111,11 +126,11 @@ module SimpleDrilldown
|
|
111
126
|
end
|
112
127
|
includes.uniq!
|
113
128
|
end
|
114
|
-
rows =
|
129
|
+
rows = c_target_class.unscoped.where(c_base_condition)
|
115
130
|
.select("#{query[:select]} AS value")
|
116
|
-
.where(filter_conditions)
|
117
|
-
.where(query[:where])
|
118
|
-
.joins(make_join([],
|
131
|
+
.where(filter_conditions || '1=1')
|
132
|
+
.where(query[:where] || '1=1')
|
133
|
+
.joins(make_join([], c_target_class.name.underscore.to_sym, includes))
|
119
134
|
.order('value')
|
120
135
|
.group(:value)
|
121
136
|
.to_a
|
@@ -137,14 +152,14 @@ module SimpleDrilldown
|
|
137
152
|
end
|
138
153
|
|
139
154
|
def make_conditions(search_filter)
|
140
|
-
includes =
|
155
|
+
includes = c_base_includes.dup
|
141
156
|
if search_filter
|
142
157
|
condition_strings = []
|
143
158
|
condition_values = []
|
144
159
|
|
145
160
|
filter_texts = []
|
146
161
|
search_filter.each do |field, values|
|
147
|
-
dimension_def =
|
162
|
+
dimension_def = c_dimension_defs[field]
|
148
163
|
raise "Unknown filter field: #{field.inspect}" if dimension_def.nil?
|
149
164
|
|
150
165
|
values = [*values]
|
@@ -254,24 +269,7 @@ module SimpleDrilldown
|
|
254
269
|
|
255
270
|
def initialize
|
256
271
|
super()
|
257
|
-
@
|
258
|
-
@default_fields = @@default_fields
|
259
|
-
@default_select_value = SimpleDrilldown::Search::SelectValue::COUNT
|
260
|
-
@target_class = @@target_class
|
261
|
-
@select = @@select
|
262
|
-
@@base_condition = '1 = 1' unless defined?(@@base_condition)
|
263
|
-
@base_condition = @@base_condition
|
264
|
-
@@base_includes = [] unless defined?(@@base_includes)
|
265
|
-
@base_includes = @@base_includes
|
266
|
-
@base_group = defined?(@@base_group) ? @@base_group : []
|
267
|
-
@@list_includes = [] unless defined?(@@list_includes)
|
268
|
-
@list_includes = @@list_includes
|
269
|
-
@list_order = @@list_order
|
270
|
-
@dimension_defs = @@dimension_defs
|
271
|
-
@@summary_fields = [] unless defined?(@@summary_fields)
|
272
|
-
@summary_fields = @@summary_fields
|
273
|
-
|
274
|
-
@history_fields = @fields.select { |_k, v| v[:list_change_times] }.map { |k, _v| k.to_s }
|
272
|
+
@history_fields = c_fields.select { |_k, v| v[:list_change_times] }.map { |k, _v| k.to_s }
|
275
273
|
end
|
276
274
|
|
277
275
|
# ?dimension[0]=supplier&dimension[1]=transaction_type&
|
@@ -279,18 +277,17 @@ module SimpleDrilldown
|
|
279
277
|
def index(do_render = true)
|
280
278
|
@search = new_search_object
|
281
279
|
|
282
|
-
@transaction_fields = (@search.fields + (
|
283
|
-
@transaction_fields_map = @fields
|
280
|
+
@transaction_fields = (@search.fields + (c_fields.keys.map(&:to_s) - @search.fields))
|
284
281
|
|
285
|
-
select =
|
286
|
-
includes =
|
282
|
+
select = c_select.dup
|
283
|
+
includes = c_base_includes.dup
|
287
284
|
|
288
285
|
@dimensions = []
|
289
|
-
select << ", 'All'::text as value0"
|
286
|
+
select << ", 'All'#{'::text' if c_target_class.connection.adapter_name == 'PostgreSQL'} as value0"
|
290
287
|
@dimensions += @search.dimensions.map do |dn|
|
291
|
-
raise "Unknown distribution field: #{dn.inspect}" if
|
288
|
+
raise "Unknown distribution field: #{dn.inspect}" if c_dimension_defs[dn].nil?
|
292
289
|
|
293
|
-
|
290
|
+
c_dimension_defs[dn]
|
294
291
|
end
|
295
292
|
@dimensions.each_with_index do |d, i|
|
296
293
|
select << ", #{d[:select_expression]} as value#{i + 1}"
|
@@ -315,18 +312,18 @@ module SimpleDrilldown
|
|
315
312
|
order = (1..@dimensions.size).map { |i| "value#{i}" }.join(',')
|
316
313
|
order = nil if order.empty?
|
317
314
|
end
|
318
|
-
group = (
|
315
|
+
group = (c_base_group + (1..@dimensions.size).map { |i| "value#{i}" }).join(',')
|
319
316
|
group = nil if group.empty?
|
320
317
|
|
321
|
-
joins = self.class.make_join([],
|
322
|
-
rows =
|
323
|
-
|
324
|
-
|
325
|
-
|
318
|
+
joins = self.class.make_join([], c_target_class.name.underscore.to_sym, includes)
|
319
|
+
rows = c_target_class.unscoped.where(c_base_condition).select(select).where(conditions)
|
320
|
+
.joins(joins)
|
321
|
+
.group(group)
|
322
|
+
.order(order).to_a
|
326
323
|
|
327
324
|
if rows.empty?
|
328
325
|
@result = { value: 'All', count: 0, row_count: 0, nodes: 0, rows: [] }
|
329
|
-
|
326
|
+
c_summary_fields.each { |f| @result[f] = 0 }
|
330
327
|
else
|
331
328
|
if do_render && @search.list && rows.inject(0) { |sum, r| sum + r[:count].to_i } > LIST_LIMIT
|
332
329
|
@search.list = false
|
@@ -335,9 +332,9 @@ module SimpleDrilldown
|
|
335
332
|
@result = result_from_rows(rows, 0, 0, ['All'])
|
336
333
|
end
|
337
334
|
|
338
|
-
remove_duplicates(@result) unless
|
335
|
+
remove_duplicates(@result) unless c_base_group.empty?
|
339
336
|
|
340
|
-
@remaining_dimensions =
|
337
|
+
@remaining_dimensions = c_dimension_defs.dup
|
341
338
|
@remaining_dimensions.each_key do |dim_name|
|
342
339
|
if (@search.filter[dim_name] && @search.filter[dim_name].size == 1) ||
|
343
340
|
(@dimensions.any? { |d| d[:url_param_name] == dim_name })
|
@@ -352,9 +349,9 @@ module SimpleDrilldown
|
|
352
349
|
def choices
|
353
350
|
@search = new_search_object
|
354
351
|
dimension_name = params[:dimension_name]
|
355
|
-
dimension =
|
352
|
+
dimension = c_dimension_defs[dimension_name]
|
356
353
|
selected = @search.filter[dimension_name] || []
|
357
|
-
raise "Unknown dimension #{dimension_name.inspect}: #{
|
354
|
+
raise "Unknown dimension #{dimension_name.inspect}: #{c_dimension_defs.keys.inspect}" unless dimension
|
358
355
|
|
359
356
|
choices = [[t(:all), nil]] +
|
360
357
|
(dimension[:legal_values]&.call(@search)&.map { |o| o.is_a?(Array) ? o[0..1].map(&:to_s) : o.to_s } || [])
|
@@ -398,7 +395,7 @@ module SimpleDrilldown
|
|
398
395
|
private
|
399
396
|
|
400
397
|
def new_search_object
|
401
|
-
SimpleDrilldown::Search.new(params[:search]&.to_unsafe_h,
|
398
|
+
SimpleDrilldown::Search.new(params[:search]&.to_unsafe_h, c_default_fields, c_default_select_value)
|
402
399
|
end
|
403
400
|
|
404
401
|
def remove_duplicates(result)
|
@@ -411,7 +408,7 @@ module SimpleDrilldown
|
|
411
408
|
if prev_row
|
412
409
|
if prev_row[:value] == r[:value]
|
413
410
|
prev_row[:count] += r[:count]
|
414
|
-
|
411
|
+
c_summary_fields.each do |f|
|
415
412
|
prev_row[f] += r[f]
|
416
413
|
end
|
417
414
|
prev_row[:row_count] = [prev_row[:row_count], r[:row_count]].max
|
@@ -449,7 +446,7 @@ module SimpleDrilldown
|
|
449
446
|
row_count: 0,
|
450
447
|
nodes: 0
|
451
448
|
}
|
452
|
-
|
449
|
+
c_summary_fields.each { |f| sub_result[f] = 0 }
|
453
450
|
sub_result[:rows] = add_zero_results([], dimension + 1) if dimension < @dimensions.size - 1
|
454
451
|
result_rows << sub_result
|
455
452
|
end
|
@@ -472,7 +469,7 @@ module SimpleDrilldown
|
|
472
469
|
row_count: 1,
|
473
470
|
nodes: @search.list ? 2 : 1
|
474
471
|
}
|
475
|
-
|
472
|
+
c_summary_fields.each { |f| result[f] = row[f].to_i }
|
476
473
|
return result
|
477
474
|
end
|
478
475
|
|
@@ -495,7 +492,7 @@ module SimpleDrilldown
|
|
495
492
|
nodes: result_rows.inject(0) { |t, r| t + r[:nodes] } + 1,
|
496
493
|
rows: result_rows
|
497
494
|
}
|
498
|
-
|
495
|
+
c_summary_fields.each { |f| result[f] = result_rows.inject(0) { |t, r| t + r[f] } }
|
499
496
|
result
|
500
497
|
end
|
501
498
|
|
@@ -505,9 +502,9 @@ module SimpleDrilldown
|
|
505
502
|
populate_list(conditions, includes, r, values + [r[:value]])
|
506
503
|
end
|
507
504
|
else
|
508
|
-
list_includes = includes +
|
505
|
+
list_includes = includes + c_list_includes
|
509
506
|
@search.fields.each do |field|
|
510
|
-
field_def =
|
507
|
+
field_def = c_fields[field.to_sym]
|
511
508
|
raise "Field definition missing for: #{field.inspect}" unless field_def
|
512
509
|
|
513
510
|
field_includes = field_def[:include]
|
@@ -521,9 +518,9 @@ module SimpleDrilldown
|
|
521
518
|
list_includes << { assignment: { order: :"#{f}_changes" } } if @search.fields.include? f
|
522
519
|
end
|
523
520
|
end
|
524
|
-
joins = self.class.make_join([],
|
521
|
+
joins = self.class.make_join([], c_target_class.name.underscore.to_sym, list_includes)
|
525
522
|
list_conditions = list_conditions(conditions, values)
|
526
|
-
base_query =
|
523
|
+
base_query = c_target_class.unscoped.where(c_base_condition).joins(joins).order(@list_order)
|
527
524
|
base_query = base_query.where(list_conditions) if list_conditions
|
528
525
|
result[:transactions] = base_query.to_a
|
529
526
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'chartkick'
|
4
|
+
|
3
5
|
module SimpleDrilldown
|
4
6
|
class Engine < ::Rails::Engine
|
5
7
|
isolate_namespace SimpleDrilldown
|
8
|
+
config.autoload_paths << File.dirname(__dir__)
|
6
9
|
|
7
10
|
initializer 'simple_drilldown.assets.precompile' do |app|
|
8
11
|
app.config.assets.precompile += %w[chartkick.js]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_drilldown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uwe Kubosch
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chartkick
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- lib/generators/drilldown_controller/USAGE
|
124
124
|
- lib/generators/drilldown_controller/drilldown_controller_generator.rb
|
125
125
|
- lib/generators/drilldown_controller/templates/drilldown_controller.rb.erb
|
126
|
+
- lib/generators/drilldown_controller/templates/drilldown_controller_test.rb.erb
|
126
127
|
- lib/simple_drilldown.rb
|
127
128
|
- lib/simple_drilldown/drilldown_controller.rb
|
128
129
|
- lib/simple_drilldown/drilldown_helper.rb
|
@@ -136,7 +137,7 @@ licenses:
|
|
136
137
|
- MIT
|
137
138
|
metadata:
|
138
139
|
allowed_push_host: https://rubygems.org/
|
139
|
-
post_install_message:
|
140
|
+
post_install_message:
|
140
141
|
rdoc_options: []
|
141
142
|
require_paths:
|
142
143
|
- lib
|
@@ -152,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
153
|
version: '0'
|
153
154
|
requirements: []
|
154
155
|
rubygems_version: 3.1.2
|
155
|
-
signing_key:
|
156
|
+
signing_key:
|
156
157
|
specification_version: 4
|
157
158
|
summary: Simple data warehouse and drilldown.
|
158
159
|
test_files: []
|