rorschart 0.8.0 → 0.10.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/Gemfile.lock +1 -1
- data/lib/rorschart/google_chart_mapper.rb +45 -0
- data/lib/rorschart/google_chart_options.rb +81 -0
- data/lib/rorschart/helper.rb +43 -232
- data/lib/rorschart/multiple_series.rb +71 -0
- data/lib/rorschart/pivot_data.rb +88 -0
- data/lib/rorschart/version.rb +1 -1
- data/lib/rorschart.rb +1 -0
- data/test/{rorschart_test.rb → google_chart_mapper_test.rb} +107 -33
- data/test/pivot_data_test.rb +33 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a74ccb096f456a6ede1d3842a61e149d6245b46
|
4
|
+
data.tar.gz: ac5be7dcb098e4501fe559d7866833e9a35ff92e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a54a4e71280208bb2485d6f3da251e34c3bd22c1719d9672a41b9c74aa5a5f35cbd5c426f2d4cfaa02c1fada2dcf422c10e34f32eefce0cc12e0f5cb96cdfeb
|
7
|
+
data.tar.gz: 2168376181ca0e094c06d49ef0055db98747efa87419bf48d0a3b4d5a5506a29f59f9568b57d493b69823f46b40346637a43178ebe7f18b89dd3f5f8d5142bf9
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rorschart
|
2
|
+
module GoogleChart
|
3
|
+
module Mapper
|
4
|
+
|
5
|
+
require 'rorschart/pivot_data'
|
6
|
+
|
7
|
+
def format_if_needed(data_source)
|
8
|
+
data_source.is_a?(String) ? data_source : to_datatable_format(data_source)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_datatable_format(data)
|
12
|
+
|
13
|
+
return data if is_already_converted? data
|
14
|
+
|
15
|
+
if (data.is_a? Rorschart::MultipleSeries)
|
16
|
+
pivot = data
|
17
|
+
else
|
18
|
+
pivot = PivotData.new(data)
|
19
|
+
pivot.sort_by_date!
|
20
|
+
end
|
21
|
+
|
22
|
+
return {cols: pivot.cols, rows: add_rows(pivot.rows) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def is_already_converted?(data)
|
26
|
+
(data.class == Hash) and (data.keys == ["cols", "rows"])
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_rows(rows)
|
30
|
+
rows.map{|row|
|
31
|
+
{"c" =>
|
32
|
+
row.map{|col|
|
33
|
+
{"v" => col}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def chart_class_from_string(klass_symbol)
|
40
|
+
"google.visualization." + klass_symbol.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Rorschart
|
2
|
+
module GoogleChart
|
3
|
+
module Options
|
4
|
+
|
5
|
+
def default_options
|
6
|
+
{
|
7
|
+
fontName: "'Helvetica Neue', Helvetica, Arial, sans-serif",
|
8
|
+
pointSize: 8,
|
9
|
+
lineWidth: 3,
|
10
|
+
chartArea: {
|
11
|
+
width: '100%',
|
12
|
+
height: '70%'
|
13
|
+
},
|
14
|
+
titlePosition: 'out',
|
15
|
+
axisTitlesPosition: 'in',
|
16
|
+
legend: {
|
17
|
+
textStyle: {
|
18
|
+
fontSize: 12,
|
19
|
+
color: "#444"
|
20
|
+
},
|
21
|
+
alignment: "end",
|
22
|
+
position: "top"
|
23
|
+
},
|
24
|
+
curveType: "function",
|
25
|
+
hAxis: {
|
26
|
+
textStyle: {
|
27
|
+
color: "#666",
|
28
|
+
fontSize: 12
|
29
|
+
},
|
30
|
+
gridlines: {
|
31
|
+
color: "transparent"
|
32
|
+
},
|
33
|
+
baselineColor: "#ccc",
|
34
|
+
viewWindow: {}
|
35
|
+
},
|
36
|
+
vAxis: {
|
37
|
+
textStyle: {
|
38
|
+
color: "#666",
|
39
|
+
fontSize: 12
|
40
|
+
},
|
41
|
+
textPosition: 'in',
|
42
|
+
baselineColor: "#ccc",
|
43
|
+
viewWindow: {}
|
44
|
+
},
|
45
|
+
tooltip: {
|
46
|
+
textStyle: {
|
47
|
+
color: "#666",
|
48
|
+
fontSize: 12
|
49
|
+
}
|
50
|
+
},
|
51
|
+
#A nice Color Scheme from http://www.colourlovers.com/palettes/top
|
52
|
+
colors: ['#00A0B0', '#6A4A3C', '#CC333F', '#EB6841', '#EDC951'],
|
53
|
+
# colors: ['#F8FCC1', '#CC0C39', '#E6781E', '#C8CF02', '#1693A7'],
|
54
|
+
allowHtml: true
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def chart_options(klass_symbol)
|
59
|
+
{
|
60
|
+
"Table" => {
|
61
|
+
cssClassNames: {
|
62
|
+
tableRow: 'table_row',
|
63
|
+
headerRow: 'header_row',
|
64
|
+
headerCell: 'header_cel'
|
65
|
+
},
|
66
|
+
height: "100%"
|
67
|
+
},
|
68
|
+
"AreaChart" => {
|
69
|
+
isStacked: true,
|
70
|
+
},
|
71
|
+
"PieChart" => {
|
72
|
+
legend: {
|
73
|
+
alignment: "start",
|
74
|
+
position: "right"
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}[klass_symbol] || {}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/rorschart/helper.rb
CHANGED
@@ -1,125 +1,53 @@
|
|
1
1
|
require "json"
|
2
2
|
require "erb"
|
3
|
+
require "rorschart/google_chart_mapper"
|
4
|
+
require "rorschart/google_chart_options"
|
3
5
|
|
4
6
|
module Rorschart
|
5
|
-
module Helper
|
6
|
-
|
7
|
-
def default_options
|
8
|
-
{
|
9
|
-
fontName: "'Helvetica Neue', Helvetica, Arial, sans-serif",
|
10
|
-
pointSize: 8,
|
11
|
-
lineWidth: 3,
|
12
|
-
chartArea: {
|
13
|
-
width: '100%',
|
14
|
-
height: '70%'
|
15
|
-
},
|
16
|
-
titlePosition: 'out',
|
17
|
-
axisTitlesPosition: 'in',
|
18
|
-
legend: {
|
19
|
-
textStyle: {
|
20
|
-
fontSize: 12,
|
21
|
-
color: "#444"
|
22
|
-
},
|
23
|
-
alignment: "end",
|
24
|
-
position: "top"
|
25
|
-
},
|
26
|
-
curveType: "function",
|
27
|
-
hAxis: {
|
28
|
-
textStyle: {
|
29
|
-
color: "#666",
|
30
|
-
fontSize: 12
|
31
|
-
},
|
32
|
-
gridlines: {
|
33
|
-
color: "transparent"
|
34
|
-
},
|
35
|
-
baselineColor: "#ccc",
|
36
|
-
viewWindow: {}
|
37
|
-
},
|
38
|
-
vAxis: {
|
39
|
-
textStyle: {
|
40
|
-
color: "#666",
|
41
|
-
fontSize: 12
|
42
|
-
},
|
43
|
-
textPosition: 'in',
|
44
|
-
baselineColor: "#ccc",
|
45
|
-
viewWindow: {}
|
46
|
-
},
|
47
|
-
tooltip: {
|
48
|
-
textStyle: {
|
49
|
-
color: "#666",
|
50
|
-
fontSize: 12
|
51
|
-
}
|
52
|
-
},
|
53
|
-
#A nice Color Scheme from http://www.colourlovers.com/palettes/top
|
54
|
-
colors: ['#00A0B0', '#6A4A3C', '#CC333F', '#EB6841', '#EDC951'],
|
55
|
-
# colors: ['#F8FCC1', '#CC0C39', '#E6781E', '#C8CF02', '#1693A7'],
|
56
|
-
allowHtml: true
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
def chart_options(klass_symbol)
|
61
|
-
{
|
62
|
-
"Table" => {
|
63
|
-
cssClassNames: {
|
64
|
-
tableRow: 'table_row',
|
65
|
-
headerRow: 'header_row',
|
66
|
-
headerCell: 'header_cel'
|
67
|
-
},
|
68
|
-
height: "100%"
|
69
|
-
},
|
70
|
-
"AreaChart" => {
|
71
|
-
isStacked: true,
|
72
|
-
},
|
73
|
-
"PieChart" => {
|
74
|
-
legend: {
|
75
|
-
alignment: "start",
|
76
|
-
position: "right"
|
77
|
-
}
|
78
|
-
}
|
79
|
-
}[klass_symbol] || {}
|
80
|
-
end
|
81
7
|
|
82
|
-
|
83
|
-
|
84
|
-
|
8
|
+
module Helper
|
9
|
+
|
10
|
+
def line_chart(data_source, options = {})
|
11
|
+
rorschart_chart "LineChart", data_source, options
|
12
|
+
end
|
85
13
|
|
86
|
-
|
87
|
-
|
88
|
-
|
14
|
+
def pie_chart(data_source, options = {})
|
15
|
+
rorschart_chart "PieChart", data_source, options
|
16
|
+
end
|
89
17
|
|
90
|
-
|
91
|
-
|
92
|
-
|
18
|
+
def column_chart(data_source, options = {})
|
19
|
+
rorschart_chart "ColumnChart", data_source, options
|
20
|
+
end
|
93
21
|
|
94
|
-
|
95
|
-
|
96
|
-
|
22
|
+
def bar_chart(data_source, options = {})
|
23
|
+
rorschart_chart "BarChart", data_source, options
|
24
|
+
end
|
97
25
|
|
98
|
-
|
99
|
-
|
100
|
-
|
26
|
+
def area_chart(data_source, options = {})
|
27
|
+
rorschart_chart "AreaChart", data_source, options
|
28
|
+
end
|
101
29
|
|
102
|
-
|
103
|
-
|
104
|
-
|
30
|
+
def table_chart(data_source, options = {})
|
31
|
+
rorschart_chart "Table", data_source, options
|
32
|
+
end
|
105
33
|
|
106
|
-
|
107
|
-
|
108
|
-
|
34
|
+
def geo_chart(data_source, options = {})
|
35
|
+
rorschart_chart "GeoChart", data_source, options
|
36
|
+
end
|
109
37
|
|
110
|
-
|
111
|
-
|
112
|
-
|
38
|
+
def to_chart(data_source)
|
39
|
+
to_datatable_format(data_source).to_json
|
40
|
+
end
|
113
41
|
|
114
|
-
|
42
|
+
def rorschart_chart(klass_name, dataSource, options = {})
|
115
43
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
44
|
+
dataSource = format_if_needed(dataSource)
|
45
|
+
element_id = options.delete(:id) || generateChartId
|
46
|
+
options = default_options.merge(chart_options(klass_name)).deep_merge(options);
|
47
|
+
height = options.delete(:height) || "300px"
|
120
48
|
|
121
|
-
|
122
|
-
|
49
|
+
html = <<HTML
|
50
|
+
<div id="#{ERB::Util.html_escape(element_id)}" style="height: #{ERB::Util.html_escape(height)}; width:100%;">
|
123
51
|
Rorchart is not initialized.
|
124
52
|
</div>
|
125
53
|
HTML
|
@@ -130,135 +58,18 @@ HTML
|
|
130
58
|
</script>
|
131
59
|
JS
|
132
60
|
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
private
|
137
|
-
|
138
|
-
|
139
|
-
def format_if_needed(data_source)
|
140
|
-
data_source.is_a?(String) ? data_source : to_datatable_format(data_source)
|
141
|
-
end
|
142
|
-
|
143
|
-
def to_datatable_format(data)
|
144
|
-
|
145
|
-
data = convert_objects_to_array_of_hash(data)
|
146
|
-
data = merge_series(data)
|
147
|
-
|
148
|
-
case data
|
149
|
-
when Array
|
150
|
-
|
151
|
-
case data.first
|
152
|
-
when Array
|
153
|
-
cols = columns_from_array_row(data.first)
|
154
|
-
rows = add_rows data
|
155
|
-
|
156
|
-
when Hash
|
157
|
-
cols = columns_from_hash_row(data)
|
158
|
-
rows = add_rows data.map{|row| row.values}
|
159
|
-
end
|
160
|
-
|
161
|
-
when Hash
|
162
|
-
cols = columns_from_array_row(data.first)
|
163
|
-
rows = add_rows data
|
164
|
-
end
|
165
|
-
|
166
|
-
return {cols: cols, rows: rows}
|
167
|
-
end
|
168
|
-
|
169
|
-
def merge_series(data)
|
170
|
-
|
171
|
-
return data if data.first.nil? || data.first.is_a?(Array)
|
172
|
-
prototype = flatten_array_hash(data).inject({}) { |h, (k, v)| h[k] = nil; h }
|
173
|
-
return data if prototype.values.size > 3
|
174
|
-
|
175
|
-
series = {}
|
176
|
-
data.each { |e|
|
177
|
-
key = e.values.first
|
178
|
-
series[key] = series[key] ? convert_grouped_values_into_series(series[key], e) : prototype.merge(e)
|
179
|
-
}
|
180
|
-
|
181
|
-
if series.keys[0].is_a? Date
|
182
|
-
series.sort.collect{|e| e[1]}
|
183
|
-
else
|
184
|
-
series.values
|
61
|
+
(html + js).html_safe
|
185
62
|
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def convert_grouped_values_into_series(serieA, serieB)
|
189
|
-
# if (serieB.values.size == 3)
|
190
|
-
# serieA.merge({serieB.values[1] => serieB.values[2]})
|
191
|
-
# else
|
192
|
-
# serieA.merge(serieB)
|
193
|
-
# end
|
194
|
-
serieA.merge(serieB)
|
195
|
-
end
|
196
|
-
|
197
|
-
def flatten_array_hash(data)
|
198
|
-
data.inject({}){|row, hash| row.merge(hash)}
|
199
|
-
end
|
200
|
-
|
201
|
-
def add_rows(rows)
|
202
|
-
rows.map{|row|
|
203
|
-
{"c" =>
|
204
|
-
row.map{|col|
|
205
|
-
{"v" => col}
|
206
|
-
}
|
207
|
-
}
|
208
|
-
}
|
209
|
-
end
|
210
|
-
|
211
|
-
def generateChartId
|
212
|
-
@current_chart_id ||= 0
|
213
|
-
"chart#{@current_chart_id += 1}"
|
214
|
-
end
|
215
|
-
|
216
|
-
def convert_objects_to_array_of_hash(data)
|
217
|
-
|
218
|
-
data = data.to_a if data.is_a? ActiveRecord::Relation
|
219
|
-
data = [] << data if data.is_a? ActiveRecord::Base
|
220
|
-
|
221
|
-
if data.is_a? Array and data.first.is_a? ActiveRecord::Base
|
222
|
-
data = data.map{|m| model_to_hash_without_empty_primary_key(m)}
|
223
|
-
end
|
224
|
-
|
225
|
-
return data
|
226
|
-
end
|
227
|
-
|
228
|
-
def model_to_hash_without_empty_primary_key(object)
|
229
|
-
primary_keys = object.class.columns.map{|c| c.name if c.primary}.compact
|
230
|
-
object.attributes.except(primary_keys.first)
|
231
|
-
end
|
232
|
-
|
233
|
-
def chart_class_from_string(klass_symbol)
|
234
|
-
"google.visualization." + klass_symbol.to_s
|
235
|
-
end
|
236
|
-
|
237
|
-
def columns_from_hash_row(data)
|
238
|
-
hash_row = flatten_array_hash(data)
|
239
|
-
hash_row.map { |c|
|
240
|
-
{:type => type_to_string(c[1]), :label => c[0]}
|
241
|
-
}
|
242
|
-
end
|
243
63
|
|
244
|
-
|
245
|
-
array_row.map { |c|
|
246
|
-
{:type => type_to_string(c), :label => default_label_for_type(c)}
|
247
|
-
}
|
248
|
-
end
|
64
|
+
private
|
249
65
|
|
250
|
-
|
251
|
-
|
252
|
-
return 'datetime' if (cel.is_a? DateTime) or (cel.is_a? Time)
|
253
|
-
return 'date' if cel.is_a? Date
|
254
|
-
return 'boolean' if (!!cel == cel)
|
255
|
-
return 'string'
|
256
|
-
end
|
66
|
+
include Rorschart::GoogleChart::Mapper
|
67
|
+
include Rorschart::GoogleChart::Options
|
257
68
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
69
|
+
def generateChartId
|
70
|
+
@current_chart_id ||= 0
|
71
|
+
"chart#{@current_chart_id += 1}"
|
72
|
+
end
|
262
73
|
|
263
74
|
end
|
264
75
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Rorschart
|
2
|
+
class MultipleSeries
|
3
|
+
|
4
|
+
attr_accessor :raw_series, :pivot_series
|
5
|
+
|
6
|
+
def initialize(raw_series)
|
7
|
+
@raw_series = raw_series
|
8
|
+
@pivot_series = raw_series.collect { |serie|
|
9
|
+
PivotData.new(serie)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def cols
|
14
|
+
cols_with_dup = @pivot_series.inject([]) { |cols, series|
|
15
|
+
cols + series.cols
|
16
|
+
}
|
17
|
+
|
18
|
+
cols_with_dup.uniq
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def rows
|
23
|
+
# create union of all series first columns, to represent all abscisse values available
|
24
|
+
union_x = union_of_first_columns()
|
25
|
+
|
26
|
+
# Preparation: store all series rows in a hash indexed by first column
|
27
|
+
series_indexed = []
|
28
|
+
@pivot_series.each { |serie|
|
29
|
+
series_indexed << index_series_by_first_col(serie)
|
30
|
+
}
|
31
|
+
|
32
|
+
# The Merge:
|
33
|
+
# For abscisse value, grab for each serie the corresponding row - or nil
|
34
|
+
union_series = []
|
35
|
+
union_x.each { |x|
|
36
|
+
row = [x]
|
37
|
+
series_indexed.each { |serie_hash|
|
38
|
+
row << serie_hash[x]
|
39
|
+
}
|
40
|
+
union_series << row.flatten
|
41
|
+
}
|
42
|
+
|
43
|
+
# Return union of all series
|
44
|
+
union_series
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def uniq_label(label)
|
50
|
+
end
|
51
|
+
|
52
|
+
def union_of_first_columns
|
53
|
+
(
|
54
|
+
@pivot_series.inject([]) { |union, serie|
|
55
|
+
union + serie.rows
|
56
|
+
}
|
57
|
+
).collect{|r| r[0]}.uniq.sort
|
58
|
+
end
|
59
|
+
|
60
|
+
def index_series_by_first_col(serie)
|
61
|
+
|
62
|
+
serie_hash = {}
|
63
|
+
serie.rows.each { |row|
|
64
|
+
serie_hash[row[0]] = row.drop(1)
|
65
|
+
}
|
66
|
+
|
67
|
+
serie_hash
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Rorschart
|
2
|
+
|
3
|
+
class PivotData
|
4
|
+
|
5
|
+
attr_accessor :cols, :rows
|
6
|
+
|
7
|
+
def initialize(raw_data)
|
8
|
+
|
9
|
+
data = convert_objects_to_array_of_hash(raw_data)
|
10
|
+
data = data.to_pivot if data.is_a? Rorschart::MultipleSeries
|
11
|
+
|
12
|
+
case data
|
13
|
+
when Array
|
14
|
+
case data.first
|
15
|
+
when Array
|
16
|
+
cols = columns_from_array_row(data.first)
|
17
|
+
when Hash
|
18
|
+
cols = columns_from_hash_row(data)
|
19
|
+
data = data.map{|row| row.values}
|
20
|
+
end
|
21
|
+
when Hash
|
22
|
+
cols = columns_from_array_row(data.first)
|
23
|
+
end
|
24
|
+
|
25
|
+
@rows = data.to_a
|
26
|
+
@cols = cols
|
27
|
+
end
|
28
|
+
|
29
|
+
def sort_by_date!
|
30
|
+
|
31
|
+
if ['datetime', 'date'].include? @cols.first[:type]
|
32
|
+
@rows.sort!
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def convert_objects_to_array_of_hash(data)
|
40
|
+
|
41
|
+
data = data.to_a if data.is_a? ActiveRecord::Relation
|
42
|
+
data = [] << data if data.is_a? ActiveRecord::Base
|
43
|
+
|
44
|
+
if data.is_a? Array and data.first.is_a? ActiveRecord::Base
|
45
|
+
data = data.map{|m| model_to_hash_without_empty_primary_key(m)}
|
46
|
+
end
|
47
|
+
|
48
|
+
return data
|
49
|
+
end
|
50
|
+
|
51
|
+
def model_to_hash_without_empty_primary_key(object)
|
52
|
+
primary_keys = object.class.columns.map{|c| c.name if c.primary}.compact
|
53
|
+
object.attributes.except(primary_keys.first)
|
54
|
+
end
|
55
|
+
|
56
|
+
def columns_from_hash_row(data)
|
57
|
+
hash_row = flatten_array_hash(data)
|
58
|
+
hash_row.map { |c|
|
59
|
+
{:type => type_to_string(c[1]), :label => c[0]}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def columns_from_array_row(array_row)
|
64
|
+
array_row.map { |c|
|
65
|
+
{:type => type_to_string(c), :label => default_label_for_type(c)}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def type_to_string(cel)
|
70
|
+
return 'number' if (cel.is_a? Integer) or (cel.is_a? Float) or cel.nil?
|
71
|
+
return 'datetime' if (cel.is_a? DateTime) or (cel.is_a? Time)
|
72
|
+
return 'date' if cel.is_a? Date
|
73
|
+
return 'boolean' if (!!cel == cel)
|
74
|
+
return 'string'
|
75
|
+
end
|
76
|
+
|
77
|
+
def default_label_for_type(cel)
|
78
|
+
return 'Date' if (cel.is_a? DateTime) or (cel.is_a? Date)
|
79
|
+
return 'Value'
|
80
|
+
end
|
81
|
+
|
82
|
+
def flatten_array_hash(data)
|
83
|
+
data.inject({}){|row, hash| row.merge(hash)}
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/rorschart/version.rb
CHANGED
data/lib/rorschart.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require "test_helper"
|
2
|
+
require "rorschart/google_chart_mapper"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
include Rorschart::
|
4
|
+
class TestGoogleChartMapper < Minitest::Unit::TestCase
|
5
|
+
|
6
|
+
include Rorschart::GoogleChart::Mapper
|
6
7
|
|
7
8
|
def compare_dataTable(right, left)
|
8
9
|
assert_equal right[:cols], left[:cols]
|
@@ -14,8 +15,8 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
14
15
|
|
15
16
|
# Given
|
16
17
|
data = {
|
17
|
-
DateTime.now =>
|
18
|
-
DateTime.now
|
18
|
+
DateTime.now - 1 => 18,
|
19
|
+
DateTime.now => 17
|
19
20
|
}
|
20
21
|
|
21
22
|
# When
|
@@ -28,8 +29,8 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
28
29
|
{type: 'number', label: 'Value'}
|
29
30
|
],
|
30
31
|
rows: [
|
31
|
-
{c:[{v: DateTime.now}, {v:
|
32
|
-
{c:[{v: DateTime.now
|
32
|
+
{c:[{v: DateTime.now - 1}, {v: 18}]},
|
33
|
+
{c:[{v: DateTime.now}, {v: 17}]}
|
33
34
|
]
|
34
35
|
}
|
35
36
|
|
@@ -62,6 +63,32 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
62
63
|
|
63
64
|
def test_from_an_array_of_hash_and_detect_type_and_reuse_column_name
|
64
65
|
|
66
|
+
# Given
|
67
|
+
data = [
|
68
|
+
{"collector_tstamp"=> Date.parse("2013-11-28"), "count"=> 49},
|
69
|
+
{"collector_tstamp"=> Date.parse("2013-12-02"), "count"=> 44}
|
70
|
+
]
|
71
|
+
|
72
|
+
# When
|
73
|
+
dataTable = to_datatable_format(data)
|
74
|
+
|
75
|
+
# Then
|
76
|
+
excepted = {
|
77
|
+
cols: [
|
78
|
+
{type: 'date', label: 'collector_tstamp'},
|
79
|
+
{type: 'number', label: 'count'}
|
80
|
+
],
|
81
|
+
rows: [
|
82
|
+
{c:[{v: Date.parse("2013-11-28")}, {v: 49}]},
|
83
|
+
{c:[{v: Date.parse("2013-12-02")}, {v: 44}]}
|
84
|
+
]
|
85
|
+
}
|
86
|
+
|
87
|
+
compare_dataTable excepted, dataTable
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_order_date_series
|
91
|
+
|
65
92
|
# Given
|
66
93
|
data = [
|
67
94
|
{"collector_tstamp"=> Date.parse("2013-12-02"), "count"=> 44},
|
@@ -79,7 +106,7 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
79
106
|
],
|
80
107
|
rows: [
|
81
108
|
{c:[{v: Date.parse("2013-11-28")}, {v: 49}]},
|
82
|
-
{c:[{v: Date.parse("2013-12-02")}, {v: 44}]}
|
109
|
+
{c:[{v: Date.parse("2013-12-02")}, {v: 44}]}
|
83
110
|
]
|
84
111
|
}
|
85
112
|
|
@@ -90,8 +117,8 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
90
117
|
|
91
118
|
# Given
|
92
119
|
data = [
|
93
|
-
[Date.parse("2013-
|
94
|
-
[Date.parse("2013-
|
120
|
+
[Date.parse("2013-11-28"), 49],
|
121
|
+
[Date.parse("2013-12-02"), 44]
|
95
122
|
]
|
96
123
|
|
97
124
|
# When
|
@@ -104,8 +131,8 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
104
131
|
{type: 'number', label: 'Value'}
|
105
132
|
],
|
106
133
|
rows: [
|
107
|
-
{c:[{v: Date.parse("2013-
|
108
|
-
{c:[{v: Date.parse("2013-
|
134
|
+
{c:[{v: Date.parse("2013-11-28")}, {v: 49}]},
|
135
|
+
{c:[{v: Date.parse("2013-12-02")}, {v: 44}]}
|
109
136
|
]
|
110
137
|
}
|
111
138
|
|
@@ -162,14 +189,20 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
162
189
|
end
|
163
190
|
|
164
191
|
def test_merge_two_series
|
192
|
+
|
165
193
|
# Given
|
166
|
-
|
194
|
+
serie1 = [
|
167
195
|
{"collector_tstamp"=> Date.parse("2013-12-01"), "count"=> 1},
|
168
|
-
{"collector_tstamp"=> Date.parse("2013-12-02"), "count"=> 2}
|
196
|
+
{"collector_tstamp"=> Date.parse("2013-12-02"), "count"=> 2}
|
197
|
+
]
|
198
|
+
|
199
|
+
serie2 = [
|
169
200
|
{"collector_tstamp"=> Date.parse("2013-12-02"), "visit"=> 11},
|
170
|
-
{"collector_tstamp"=> Date.parse("2013-12-03"), "visit"=> 3}
|
201
|
+
{"collector_tstamp"=> Date.parse("2013-12-03"), "visit"=> 3}
|
171
202
|
]
|
172
203
|
|
204
|
+
data = Rorschart::MultipleSeries.new [serie1, serie2]
|
205
|
+
|
173
206
|
# When
|
174
207
|
series = to_datatable_format(data)
|
175
208
|
|
@@ -191,19 +224,68 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
191
224
|
|
192
225
|
end
|
193
226
|
|
227
|
+
def test_merge_multiple_series
|
228
|
+
|
229
|
+
# Given
|
230
|
+
serie1 = [
|
231
|
+
{"collector_tstamp"=> Date.parse("2013-12-01"), "count"=> 1},
|
232
|
+
{"collector_tstamp"=> Date.parse("2013-12-02"), "count"=> 2}
|
233
|
+
]
|
234
|
+
|
235
|
+
serie2 = [
|
236
|
+
{"collector_tstamp"=> Date.parse("2013-12-02"), "visit"=> 11},
|
237
|
+
{"collector_tstamp"=> Date.parse("2013-12-03"), "visit"=> 3}
|
238
|
+
]
|
239
|
+
|
240
|
+
serie3 = [
|
241
|
+
{"collector_tstamp"=> Date.parse("2013-12-02"), "visit"=> 6},
|
242
|
+
{"collector_tstamp"=> Date.parse("2013-12-03"), "visit"=> 8},
|
243
|
+
{"collector_tstamp"=> Date.parse("2013-12-04"), "visit"=> 9}
|
244
|
+
]
|
245
|
+
|
246
|
+
|
247
|
+
data = Rorschart::MultipleSeries.new [serie1, serie2, serie3]
|
248
|
+
|
249
|
+
# When
|
250
|
+
series = to_datatable_format(data)
|
251
|
+
|
252
|
+
# Then
|
253
|
+
excepted = {
|
254
|
+
cols: [
|
255
|
+
{type: 'date', label: 'collector_tstamp'},
|
256
|
+
{type: 'number', label: 'count'},
|
257
|
+
{type: 'number', label: 'visit'}
|
258
|
+
],
|
259
|
+
rows: [
|
260
|
+
{c:[{v: Date.parse("2013-12-01")}, {v: 1}, {v: nil}, {v: nil}]},
|
261
|
+
{c:[{v: Date.parse("2013-12-02")}, {v: 2}, {v: 11}, {v: 6}]},
|
262
|
+
{c:[{v: Date.parse("2013-12-03")}, {v: nil}, {v: 3}, {v: 8}]},
|
263
|
+
{c:[{v: Date.parse("2013-12-04")}, {v: nil}, {v: nil}, {v: 9}]},
|
264
|
+
]
|
265
|
+
}
|
266
|
+
|
267
|
+
compare_dataTable excepted, series
|
268
|
+
|
269
|
+
end
|
270
|
+
|
194
271
|
def test_merge_two_series_with_first_serie_start_later
|
272
|
+
|
195
273
|
# Given
|
196
|
-
|
274
|
+
serie1 = [
|
197
275
|
{"collector_tstamp"=> Date.parse("2013-12-03"), "count"=> 1},
|
198
276
|
{"collector_tstamp"=> Date.parse("2013-12-04"), "count"=> 2},
|
199
|
-
{"collector_tstamp"=> Date.parse("2013-12-05"), "count"=> 3}
|
277
|
+
{"collector_tstamp"=> Date.parse("2013-12-05"), "count"=> 3}
|
278
|
+
]
|
200
279
|
|
280
|
+
serie2 = [
|
201
281
|
{"collector_tstamp"=> Date.parse("2013-12-01"), "visit"=> 5},
|
202
282
|
{"collector_tstamp"=> Date.parse("2013-12-02"), "visit"=> 6},
|
203
283
|
{"collector_tstamp"=> Date.parse("2013-12-03"), "visit"=> 7},
|
204
|
-
{"collector_tstamp"=> Date.parse("2013-12-04"), "visit"=> 8}
|
284
|
+
{"collector_tstamp"=> Date.parse("2013-12-04"), "visit"=> 8}
|
205
285
|
]
|
206
286
|
|
287
|
+
data = Rorschart::MultipleSeries.new [serie1, serie2]
|
288
|
+
|
207
289
|
# When
|
208
290
|
series = to_datatable_format(data)
|
209
291
|
|
@@ -226,7 +308,7 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
226
308
|
compare_dataTable excepted, series
|
227
309
|
|
228
310
|
end
|
229
|
-
|
311
|
+
|
230
312
|
# def test_convert_numeric_grouped_dy_date_and_another_field_into_multiseries
|
231
313
|
|
232
314
|
# # Given
|
@@ -287,22 +369,14 @@ class TestRorschart < Minitest::Unit::TestCase
|
|
287
369
|
# compare_dataTable excepted, dataTable
|
288
370
|
# end
|
289
371
|
|
290
|
-
def
|
291
|
-
|
372
|
+
def test_is_already_converted?
|
292
373
|
# Given
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
]
|
298
|
-
|
299
|
-
# When
|
300
|
-
flat = flatten_array_hash(data)
|
301
|
-
|
302
|
-
# Then
|
303
|
-
excepted = {:a => 2, :b => 2, :c => 4}
|
374
|
+
data_converted = {
|
375
|
+
"cols" => [{type: 'number', label: 'count'}],
|
376
|
+
"rows" => []
|
377
|
+
}
|
304
378
|
|
305
|
-
assert_equal
|
379
|
+
assert_equal true, is_already_converted?(data_converted)
|
306
380
|
end
|
307
381
|
|
308
382
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rorschart/pivot_data"
|
3
|
+
|
4
|
+
module Rorschart
|
5
|
+
|
6
|
+
class TestPivotData < Minitest::Unit::TestCase
|
7
|
+
|
8
|
+
def test_flatten_data
|
9
|
+
|
10
|
+
# Given
|
11
|
+
data = [
|
12
|
+
{:a => 1, :b => 2},
|
13
|
+
{:a => 2, :b => 3},
|
14
|
+
{:b => 2, :c => 4}
|
15
|
+
]
|
16
|
+
|
17
|
+
# When
|
18
|
+
|
19
|
+
pivot_data = PivotData.new(nil)
|
20
|
+
flat = pivot_data.send(:flatten_array_hash, data)
|
21
|
+
|
22
|
+
# flat = flatten_array_hash(data)
|
23
|
+
|
24
|
+
# Then
|
25
|
+
excepted = {:a => 2, :b => 2, :c => 4}
|
26
|
+
|
27
|
+
assert_equal excepted, flat
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rorschart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Pantera
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -98,11 +98,16 @@ files:
|
|
98
98
|
- app/assets/stylesheets/rorschart.css
|
99
99
|
- lib/rorschart.rb
|
100
100
|
- lib/rorschart/engine.rb
|
101
|
+
- lib/rorschart/google_chart_mapper.rb
|
102
|
+
- lib/rorschart/google_chart_options.rb
|
101
103
|
- lib/rorschart/helper.rb
|
104
|
+
- lib/rorschart/multiple_series.rb
|
105
|
+
- lib/rorschart/pivot_data.rb
|
102
106
|
- lib/rorschart/rails.rb
|
103
107
|
- lib/rorschart/version.rb
|
104
108
|
- rorschart.gemspec
|
105
|
-
- test/
|
109
|
+
- test/google_chart_mapper_test.rb
|
110
|
+
- test/pivot_data_test.rb
|
106
111
|
- test/test_helper.rb
|
107
112
|
homepage: https://github.com/epantera/rorschart
|
108
113
|
licenses:
|
@@ -129,5 +134,6 @@ signing_key:
|
|
129
134
|
specification_version: 4
|
130
135
|
summary: Beautiful Google Charts from Rails data structures
|
131
136
|
test_files:
|
132
|
-
- test/
|
137
|
+
- test/google_chart_mapper_test.rb
|
138
|
+
- test/pivot_data_test.rb
|
133
139
|
- test/test_helper.rb
|