rgviz-rails 0.10 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,8 +6,12 @@ module Rgviz
6
6
  def initialize(model_class, query)
7
7
  @model_class = model_class
8
8
  @query = query
9
+ @selects = []
9
10
  @joins = {}
10
11
  @labels = {}
12
+ @pivots = {}
13
+ @group_bys = {}
14
+ @original_columns = []
11
15
  case ActiveRecord::Base.connection.adapter_name.downcase
12
16
  when 'sqlite'
13
17
  @adapter = SqliteAdapter.new
@@ -20,12 +24,15 @@ module Rgviz
20
24
  @table = Table.new
21
25
  @extra_conditions = options[:conditions]
22
26
 
27
+ process_pivot
23
28
  process_labels
29
+ process_options
24
30
 
25
31
  generate_columns
26
32
  generate_conditions
27
33
  generate_group
28
34
  generate_order
35
+
29
36
  generate_rows
30
37
 
31
38
  @table
@@ -39,6 +46,33 @@ module Rgviz
39
46
  end
40
47
  end
41
48
 
49
+ def process_options
50
+ return unless @query.options.present?
51
+
52
+ @query.options.each do |option|
53
+ case option.option
54
+ when Option::NoValues
55
+ @no_values = true
56
+ when Option::NoFormat
57
+ @no_format = true
58
+ end
59
+ end
60
+ end
61
+
62
+ def process_pivot
63
+ if @query.pivot
64
+ @query.pivot.columns.each do |column|
65
+ @pivots[column.to_s] = true
66
+ end
67
+ end
68
+
69
+ if @query.group_by
70
+ @query.group_by.columns.each do |column|
71
+ @group_bys[column.to_s] = true
72
+ end
73
+ end
74
+ end
75
+
42
76
  def add_joins(joins)
43
77
  map = @joins
44
78
  joins.each do |join|
@@ -50,14 +84,15 @@ module Rgviz
50
84
  end
51
85
 
52
86
  def generate_columns
53
- @selects = []
54
-
55
87
  if @query.select && @query.select.columns.present?
56
88
  # Select the specified columns
57
89
  i = 0
58
90
  @query.select.columns.each do |col|
59
- @table.cols << (Column.new :id => column_id(col, i), :type => column_type(col), :label => column_label(col.to_s))
91
+ col_to_s = col.to_s
92
+
93
+ @table.cols << (Column.new :id => column_id(col, i), :type => column_type(col), :label => column_label(col_to_s))
60
94
  @selects << "(#{column_select(col)}) as c#{i}"
95
+ @original_columns << col_to_s
61
96
  i += 1
62
97
  end
63
98
  else
@@ -66,6 +101,19 @@ module Rgviz
66
101
  @model_class.send(:columns).each do |col|
67
102
  @table.cols << (Column.new :id => col.name, :type => (rails_column_type col), :label => column_label(col.name))
68
103
  @selects << "(#{col.name}) as c#{i}"
104
+ @original_columns << col_to_s
105
+ i += 1
106
+ end
107
+ end
108
+
109
+ # Select pivot columns
110
+ if @query.pivot
111
+ @query.pivot.columns.each do |col|
112
+ col_to_s = col.to_s
113
+
114
+ @table.cols << (Column.new :id => column_id(col, i), :type => column_type(col), :label => column_label(col_to_s))
115
+ @selects << "(#{column_select(col)}) as c#{i}"
116
+ @original_columns << col_to_s
69
117
  i += 1
70
118
  end
71
119
  end
@@ -77,6 +125,15 @@ module Rgviz
77
125
 
78
126
  def generate_group
79
127
  @group = to_string @query.group_by, ColumnVisitor if @query.group_by
128
+ pivot = to_string @query.pivot, ColumnVisitor if @query.pivot
129
+
130
+ if pivot.present?
131
+ if @group.present?
132
+ @group += ',' + pivot
133
+ else
134
+ @group = pivot
135
+ end
136
+ end
80
137
  end
81
138
 
82
139
  def generate_order
@@ -106,14 +163,102 @@ module Rgviz
106
163
  :offset => @query.offset,
107
164
  :joins => @joins
108
165
 
109
- results.each do |result|
110
- row = Row.new
111
- @table.rows << row
166
+ if @pivots.empty?
167
+ # Simple, just convert the results to a table
168
+ results.each do |result|
169
+ row = Row.new
170
+ @table.rows << row
171
+
172
+ i = 0
173
+ @table.cols.each do |col|
174
+ hash = {}
175
+ hash[:v] = column_value(col, result.send("c#{i}")) unless @no_values
176
+ row.c << Cell.new(hash)
177
+ i += 1
178
+ end
179
+ end
180
+ else
181
+ # A little more complicated...
182
+
183
+ # This has the grouping as a key and the pivoted selection values as a key (in a list)
184
+ fin = ActiveSupport::OrderedHash.new
112
185
 
113
- i = 0
114
- @table.cols.each do |col|
115
- row.c << (Cell.new :v => column_value(col, result.send("c#{i}")))
116
- i += 1
186
+ # The uniq pivot values
187
+ uniq_pivots = []
188
+
189
+ # Fill fin and uniq_pivots
190
+ results.each do |result|
191
+
192
+ # The grouping key of this result
193
+ grouped_by = []
194
+
195
+ # The pivots of this result
196
+ pivots = []
197
+
198
+ # The selections of this result
199
+ selections = []
200
+
201
+ # Fill grouped_by, pivots and selections, as well as uniq_pivots
202
+ @table.cols.each_with_index do |col, i|
203
+ val = column_value(col, result.send("c#{i}"))
204
+ if @group_bys.include?(@original_columns[i])
205
+ grouped_by << val
206
+ elsif @pivots.include?(@original_columns[i])
207
+ pivots << val
208
+ uniq_pivots << val unless uniq_pivots.include? val
209
+ else
210
+ selections << val
211
+ end
212
+ end
213
+
214
+ # Now put all this info into fin
215
+ fin[grouped_by] = {} unless fin[grouped_by]
216
+ pivots.each do |pivot|
217
+ selections.each do |selection|
218
+ fin[grouped_by][pivot] = selection
219
+ end
220
+ end
221
+ end
222
+
223
+ # Sort the uniq pivots so the results will be sorted for a human
224
+ uniq_pivots.sort!
225
+
226
+ # Regenerate the columns info: the current info has the values
227
+ # we needed to get the info we needed
228
+ col_i = 0
229
+ new_cols = []
230
+ @original_columns.each_with_index do |original_column, i|
231
+ old_col = @table.cols[i]
232
+ if @group_bys.include?(original_column)
233
+ old_col.id = "c#{col_i}"
234
+ new_cols << @table.cols[i]
235
+ col_i += 1
236
+ elsif !@pivots.include?(original_column)
237
+ uniq_pivots.each do |uniq_pivot|
238
+ new_cols << (Column.new :id => "c#{col_i}", :type => old_col.type, :label => "#{uniq_pivot} #{old_col.label}")
239
+ col_i += 1
240
+ end
241
+ end
242
+ end
243
+
244
+ @table.cols = new_cols
245
+
246
+ # Create the rows
247
+ fin.each do |key, value|
248
+ row = Row.new
249
+ @table.rows << row
250
+
251
+ group_i = 0
252
+ @original_columns.each_with_index do |original_column, i|
253
+ if @group_bys.include?(original_column)
254
+ row.c << (Cell.new :v => key[group_i])
255
+ group_i += 1
256
+ elsif !@pivots.include?(original_column)
257
+ uniq_pivots.each do |uniq_pivot|
258
+ row.c << (Cell.new :v => value[uniq_pivot])
259
+ end
260
+ end
261
+ end
117
262
  end
118
263
  end
119
264
  end
@@ -202,11 +202,21 @@ describe Executor do
202
202
  Person.make :age => 3
203
203
 
204
204
  table = exec 'select age where age > 1', :conditions => 'age < 3'
205
+ it "processes with conditions as string" do
206
+ Person.make :age => 1
207
+ Person.make :age => 2
208
+ Person.make :age => 3
209
+
210
+ table = exec 'select age', :conditions => 'age = 2'
205
211
 
206
212
  table.rows.length.should == 1
207
213
  table.rows[0].c.length.should == 1
208
214
  table.rows[0].c[0].v.should == 2
209
215
  end
216
+ table.rows.length.should == 1
217
+ table.rows[0].c.length.should == 1
218
+ table.rows[0].c[0].v.should == 2
219
+ end
210
220
 
211
221
  it "processes with conditions as array" do
212
222
  Person.make :age => 1
@@ -276,4 +286,78 @@ describe Executor do
276
286
  Person.make :age => 2
277
287
  end
278
288
 
289
+ it_processes_single_select_column "1 options no_values", 'c0', :number, nil, "1"
290
+
291
+ it "processes pivot" do
292
+ Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 1000
293
+ Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 500
294
+ Person.make :name => 'Eng', :birthday => '2000-01-13', :age => 600
295
+ Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 400
296
+ Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 350
297
+ Person.make :name => 'Marketing', :birthday => '2000-01-13', :age => 800
298
+
299
+ table = exec 'select name, sum(age) group by name pivot birthday'
300
+
301
+ table.cols.length.should == 3
302
+
303
+ i = 0
304
+ [['c0', :string, 'name'],
305
+ ['c1', :number, '2000-01-12 sum(age)'],
306
+ ['c2', :number, '2000-01-13 sum(age)']].each do |id, type, label|
307
+ table.cols[i].id.should == id
308
+ table.cols[i].type.should == type
309
+ table.cols[i].label.should == label
310
+ i += 1
311
+ end
312
+
313
+ table.rows.length.should == 3
314
+
315
+ i = 0
316
+ [['Eng', 1500, 600],
317
+ ['Marketing', nil, 800],
318
+ ['Sales', 750, nil]].each do |values|
319
+ table.rows[i].c.length.should == 3
320
+ values.each_with_index do |v, j|
321
+ table.rows[i].c[j].v.should == v
322
+ end
323
+ i += 1
324
+ end
325
+ end
326
+
327
+ it "processes pivot2" do
328
+ Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 1000
329
+ Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 500
330
+ Person.make :name => 'Eng', :birthday => '2000-01-13', :age => 600
331
+ Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 400
332
+ Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 350
333
+ Person.make :name => 'Marketing', :birthday => '2000-01-13', :age => 800
334
+
335
+ table = exec 'select sum(age), name group by name pivot birthday'
336
+
337
+ table.cols.length.should == 3
338
+
339
+ i = 0
340
+ [['c0', :number, '2000-01-12 sum(age)'],
341
+ ['c1', :number, '2000-01-13 sum(age)'],
342
+ ['c2', :string, 'name']].each do |id, type, label|
343
+ table.cols[i].id.should == id
344
+ table.cols[i].type.should == type
345
+ table.cols[i].label.should == label
346
+ i += 1
347
+ end
348
+
349
+ table.rows.length.should == 3
350
+
351
+ i = 0
352
+ [[1500, 600, 'Eng'],
353
+ [nil, 800, 'Marketing'],
354
+ [750, nil, 'Sales']].each do |values|
355
+ table.rows[i].c.length.should == 3
356
+ values.each_with_index do |v, j|
357
+ table.rows[i].c[j].v.should == v
358
+ end
359
+ i += 1
360
+ end
361
+ end
362
+
279
363
  end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgviz-rails
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 10
9
- version: "0.10"
8
+ - 11
9
+ version: "0.11"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ary Borenszweig