JamieFlournoy-g_viz 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/CHANGELOG +3 -0
- data/JamieFlournoy-g_viz.gemspec +58 -0
- data/Manifest +13 -0
- data/README.markdown +113 -0
- data/Rakefile +24 -0
- data/VERSION +2 -0
- data/lib/g_viz/data.rb +101 -0
- data/lib/g_viz/g_viz.rb +50 -0
- data/lib/g_viz/json_google.rb +11 -0
- data/lib/g_viz/templates/data_tables.erb +43 -0
- data/lib/g_viz.rb +5 -0
- data/spec/g_viz/fixtures/annotated_timeline.rb +44 -0
- data/spec/g_viz/g_viz_spec.rb +83 -0
- data/spec/g_viz/templates/rendered_annotated_timeline.html +41 -0
- data/spec/test_helper.rb +10 -0
- metadata +72 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{JamieFlournoy-g_viz}
|
8
|
+
s.version = "0.3.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Gary Tsang"]
|
12
|
+
s.date = %q{2009-11-25}
|
13
|
+
s.description = %q{A Ruby client for the Google Visualization API.}
|
14
|
+
s.email = %q{gary.tsang@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"CHANGELOG",
|
21
|
+
"JamieFlournoy-g_viz.gemspec",
|
22
|
+
"Manifest",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/g_viz.rb",
|
27
|
+
"lib/g_viz/data.rb",
|
28
|
+
"lib/g_viz/g_viz.rb",
|
29
|
+
"lib/g_viz/json_google.rb",
|
30
|
+
"lib/g_viz/templates/data_tables.erb",
|
31
|
+
"spec/g_viz/fixtures/annotated_timeline.rb",
|
32
|
+
"spec/g_viz/g_viz_spec.rb",
|
33
|
+
"spec/g_viz/templates/rendered_annotated_timeline.html",
|
34
|
+
"spec/test_helper.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/JamieFlournoy/g_viz}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubyforge_project = %q{none}
|
40
|
+
s.rubygems_version = %q{1.3.5}
|
41
|
+
s.summary = %q{Google Visualization API Ruby Client}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/g_viz/fixtures/annotated_timeline.rb",
|
44
|
+
"spec/g_viz/g_viz_spec.rb",
|
45
|
+
"spec/test_helper.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
+
else
|
54
|
+
end
|
55
|
+
else
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
data/Manifest
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
lib/g_viz/data.rb
|
3
|
+
lib/g_viz/g_viz.rb
|
4
|
+
lib/g_viz/json_google.rb
|
5
|
+
lib/g_viz/templates/data_tables.erb
|
6
|
+
lib/g_viz.rb
|
7
|
+
Manifest
|
8
|
+
Rakefile
|
9
|
+
README.markdown
|
10
|
+
spec/g_viz/fixtures/annotated_timeline.rb
|
11
|
+
spec/g_viz/g_viz_spec.rb
|
12
|
+
spec/g_viz/templates/rendered_annotated_timeline.html
|
13
|
+
spec/test_helper.rb
|
data/README.markdown
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# GViz
|
2
|
+
|
3
|
+
GViz is a simple Ruby wrapper for the Google Visualization API
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
### Definitions
|
8
|
+
<dl>
|
9
|
+
<dt>chart_type</dt>
|
10
|
+
<dd>Google Visualization Chart Constructor</dd>
|
11
|
+
<dt>data</dt>
|
12
|
+
<dd>An array of objects that responds to [](key) i.e. and array of Hashes</dd>
|
13
|
+
<dt>mapping</dt>
|
14
|
+
<dd>An array of key, description pairs that we are using as data points for our chart</dd>
|
15
|
+
</dl>
|
16
|
+
|
17
|
+
GViz::Base keeps track of charts that need to be rendered.
|
18
|
+
|
19
|
+
chart = GViz::Base.new
|
20
|
+
dom_id = chart.add_graph(chart_type, data, mapping, config_options)
|
21
|
+
chart.output
|
22
|
+
|
23
|
+
You can add multiple visualizations
|
24
|
+
|
25
|
+
chart = GViz::Base.new
|
26
|
+
dom_id1 = chart.add_graph(chart_type, data, mapping, config_options)
|
27
|
+
dom_id2 = chart.add_graph(chart_type, data, mapping, config_options)
|
28
|
+
chart.output
|
29
|
+
|
30
|
+
You can use dynamic adders
|
31
|
+
|
32
|
+
#chart_type for dynamic adders are lowercased and underscored
|
33
|
+
chart = GViz::Base.new
|
34
|
+
dom_id1 = chart.add_chart_type(data, mapping, config_options)
|
35
|
+
chart.output
|
36
|
+
|
37
|
+
## Examples
|
38
|
+
### AnnotatedTimeLine
|
39
|
+
|
40
|
+
mapping = [[:date, 'Date'],[:sold_pencils, 'Solid Pencils'], [:title1, 'title1'], [:text1, 'text1'],
|
41
|
+
[:sold_pens, 'Sold Pens'], [:title2, 'title2'], [:text2, 'text2']]
|
42
|
+
|
43
|
+
data = [
|
44
|
+
{:date => "2008-02-01", :sold_pencils => 30000, :sold_pens => 40645},
|
45
|
+
{:date => Date.parse("2008-02-02"), :sold_pencils => 14045, :sold_pens => 20374},
|
46
|
+
{:date => Date.parse("2008-02-03"), :sold_pencils => 55022, :sold_pens => 50766},
|
47
|
+
{:date => Date.parse("2008-02-04"), :sold_pencils => 75284, :sold_pens => 14334, :title2 => 'Out of Stock',:text2 => 'Ran out of stock on pens at 4pm'},
|
48
|
+
{:date => Date.parse("2008-02-05"), :sold_pencils => 41476, :sold_pens => 66467, :title1 => 'Bought Pens',:text2 => 'Bought 200k pens'},
|
49
|
+
{:date => Date.parse("2008-02-06"), :sold_pencils => 33322, :sold_pens => 39463, :title1 => 'Bought Pens',:text2 => 'Bought 200k pens'}
|
50
|
+
]
|
51
|
+
|
52
|
+
g = GViz::Base.new
|
53
|
+
chart_id = g.add_annotated_time_line(data, mapping)
|
54
|
+
puts g.output
|
55
|
+
puts "<div id='#{chart_id}'></div>"
|
56
|
+
|
57
|
+
Outputs
|
58
|
+
|
59
|
+
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
|
60
|
+
<script type='text/javascript'>
|
61
|
+
google.load('visualization', '1', {'packages':['annotatedtimeline']});
|
62
|
+
google.setOnLoadCallback(drawChart);
|
63
|
+
function drawChart() {
|
64
|
+
var data_0 = new google.visualization.DataTable();
|
65
|
+
data_0.addColumn('date', 'Date')
|
66
|
+
data_0.addColumn('number', 'Solid Pencils')
|
67
|
+
data_0.addColumn('string', 'title1')
|
68
|
+
data_0.addColumn('number', 'Sold Pens')
|
69
|
+
data_0.addColumn('string', 'title2')
|
70
|
+
data_0.addColumn('string', 'text2')
|
71
|
+
data_0.addRows(6)
|
72
|
+
data_0.setValue(0, 0, new Date(2008, 1, 1))
|
73
|
+
data_0.setValue(0, 1, 30000)
|
74
|
+
data_0.setValue(0, 2, '')
|
75
|
+
data_0.setValue(0, 3, 40645)
|
76
|
+
data_0.setValue(0, 4, '')
|
77
|
+
data_0.setValue(0, 5, '')
|
78
|
+
data_0.setValue(1, 0, new Date(2008, 1, 2))
|
79
|
+
data_0.setValue(1, 1, 14045)
|
80
|
+
data_0.setValue(1, 2, '')
|
81
|
+
data_0.setValue(1, 3, 20374)
|
82
|
+
data_0.setValue(1, 4, '')
|
83
|
+
data_0.setValue(1, 5, '')
|
84
|
+
data_0.setValue(2, 0, new Date(2008, 1, 3))
|
85
|
+
data_0.setValue(2, 1, 55022)
|
86
|
+
data_0.setValue(2, 2, '')
|
87
|
+
data_0.setValue(2, 3, 50766)
|
88
|
+
data_0.setValue(2, 4, '')
|
89
|
+
data_0.setValue(2, 5, '')
|
90
|
+
data_0.setValue(3, 0, new Date(2008, 1, 4))
|
91
|
+
data_0.setValue(3, 1, 75284)
|
92
|
+
data_0.setValue(3, 2, '')
|
93
|
+
data_0.setValue(3, 3, 14334)
|
94
|
+
data_0.setValue(3, 4, 'Out of Stock')
|
95
|
+
data_0.setValue(3, 5, 'Ran out of stock on pens at 4pm')
|
96
|
+
data_0.setValue(4, 0, new Date(2008, 1, 5))
|
97
|
+
data_0.setValue(4, 1, 41476)
|
98
|
+
data_0.setValue(4, 2, 'Bought Pens')
|
99
|
+
data_0.setValue(4, 3, 66467)
|
100
|
+
data_0.setValue(4, 4, '')
|
101
|
+
data_0.setValue(4, 5, 'Bought 200k pens')
|
102
|
+
data_0.setValue(5, 0, new Date(2008, 1, 6))
|
103
|
+
data_0.setValue(5, 1, 33322)
|
104
|
+
data_0.setValue(5, 2, 'Bought Pens')
|
105
|
+
data_0.setValue(5, 3, 39463)
|
106
|
+
data_0.setValue(5, 4, '')
|
107
|
+
data_0.setValue(5, 5, 'Bought 200k pens')
|
108
|
+
var chart_data_0 = new google.visualization.AnnotatedTimeline(document.getElementById('annotatedtimeline0'));
|
109
|
+
chart_data_0.draw(data_0, {});
|
110
|
+
}
|
111
|
+
</script>
|
112
|
+
<div id='annotatedtimeline0'></div>
|
113
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "JamieFlournoy-g_viz"
|
8
|
+
gemspec.summary = "Google Visualization API Ruby Client"
|
9
|
+
gemspec.email = "gary.tsang@gmail.com"
|
10
|
+
gemspec.homepage = "http://github.com/JamieFlournoy/g_viz"
|
11
|
+
gemspec.description = "A Ruby client for the Google Visualization API."
|
12
|
+
gemspec.authors = ["Gary Tsang"]
|
13
|
+
gemspec.rubyforge_project = "none"
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Run all tests"
|
20
|
+
Spec::Rake::SpecTask.new do |t|
|
21
|
+
t.libs = [File.join(File.dirname(__FILE__), 'lib', 'g_viz')]
|
22
|
+
t.fail_on_error = false
|
23
|
+
t.spec_files = FileList['spec/*.rb']
|
24
|
+
end
|
data/VERSION
ADDED
data/lib/g_viz/data.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
module GViz
|
2
|
+
class Data
|
3
|
+
|
4
|
+
def initialize(data, map)
|
5
|
+
@map = map
|
6
|
+
@data = data
|
7
|
+
@data_type = {}
|
8
|
+
import_data_types
|
9
|
+
end
|
10
|
+
|
11
|
+
def import_data_types
|
12
|
+
found_data_types = Set.new
|
13
|
+
@data.each do |x|
|
14
|
+
break if found_data_types.size == @map.size
|
15
|
+
@map.each do |k, v|
|
16
|
+
next if found_data_types.member?(k)
|
17
|
+
if x[k]
|
18
|
+
@data_type[k] = self.class.google_data_type(x[k])
|
19
|
+
found_data_types.add([k,v])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# if there is no data that responds to a mapped value, remove that mapping
|
24
|
+
@map -= (@map - found_data_types.to_a)
|
25
|
+
end
|
26
|
+
|
27
|
+
def columns
|
28
|
+
data = @map.map do |k, v|
|
29
|
+
[@data_type[k], k]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def size
|
34
|
+
@data.size
|
35
|
+
end
|
36
|
+
|
37
|
+
def rows_hash(prune = false)
|
38
|
+
@data.map do |value|
|
39
|
+
@map.inject({}) do |maps, (k, v)|
|
40
|
+
maps[k] = self.class.ruby_to_js(@data_type[k], value[k], prune)
|
41
|
+
maps
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json
|
47
|
+
@json ||= begin
|
48
|
+
{
|
49
|
+
:columns => columns.inject({}){|hash, (k,v)| hash[v] = k; hash},
|
50
|
+
:data => rows_hash
|
51
|
+
}.to_json
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def data_name
|
56
|
+
"data_#{@data.object_id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def google_data_type(value)
|
61
|
+
if value.is_a?(Numeric)
|
62
|
+
data_type = 'number'
|
63
|
+
elsif value.is_a?(Date)
|
64
|
+
data_type = 'date'
|
65
|
+
elsif value.is_a?(DateTime) || value.is_a?(Time)
|
66
|
+
data_type = 'datetime'
|
67
|
+
elsif value.respond_to?(:to_s)
|
68
|
+
if !value.match(/[^0-9.]/)
|
69
|
+
data_type = 'number'
|
70
|
+
else
|
71
|
+
if (a = Date._parse(value)).size >= 3
|
72
|
+
if a.size >= 5
|
73
|
+
data_type = 'datetime'
|
74
|
+
else
|
75
|
+
data_type = 'date'
|
76
|
+
end
|
77
|
+
else
|
78
|
+
data_type = 'string'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
data_type
|
83
|
+
end
|
84
|
+
|
85
|
+
def ruby_to_js(type, value, prune = false)
|
86
|
+
return nil if value.nil? && prune
|
87
|
+
return "" if value == "" || value.nil?
|
88
|
+
if type == 'string'
|
89
|
+
value = "#{value}"
|
90
|
+
elsif type == 'date'
|
91
|
+
value = Date.parse(value.to_s)
|
92
|
+
elsif type == 'datetime'
|
93
|
+
value = DateTime.parse(value.to_s)
|
94
|
+
elsif type == 'number'
|
95
|
+
value = value.to_s.match(/\./) ? value.to_f : value.to_i
|
96
|
+
end
|
97
|
+
return value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/g_viz/g_viz.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'data')
|
2
|
+
require File.join(File.dirname(__FILE__), 'json_google')
|
3
|
+
|
4
|
+
module GViz
|
5
|
+
class Base
|
6
|
+
|
7
|
+
def initialize(config = {})
|
8
|
+
@viz_package_names = Set.new
|
9
|
+
@config = config
|
10
|
+
@namespace = @config[:namespace] || ""
|
11
|
+
@datas = {}
|
12
|
+
@visualizations = []
|
13
|
+
@template_name = File.join(File.dirname(__FILE__), 'templates', 'data_tables.erb')
|
14
|
+
end
|
15
|
+
|
16
|
+
def output
|
17
|
+
b = binding
|
18
|
+
rhtml = ERB.new(IO.read(@template_name), 0, "-")
|
19
|
+
@output = rhtml.result(b)
|
20
|
+
return @output
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_data(data, mapping)
|
24
|
+
@datas[data.object_id] = GViz::Data.new(data, mapping)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_graph(type, dom_id, data, columns, options= {}, extra_options = {})
|
28
|
+
@viz_package_names.add(type)
|
29
|
+
new_viz = draw_visualization(type, dom_id, data, columns, options, extra_options)
|
30
|
+
@visualizations << new_viz
|
31
|
+
end
|
32
|
+
|
33
|
+
def draw_visualization(type, dom_id, data, columns, options = {}, extra_options = {})
|
34
|
+
viz_string = <<-STRING
|
35
|
+
var chart_#{data.object_id} = new google.visualization.#{type}(document.getElementById('#{dom_id}'));
|
36
|
+
chart_#{data.object_id}.draw(createDataTable(#{@datas[data.object_id].data_name}, #{columns.to_json}, #{extra_options[:first_column_title] == true ? 'true' : 'false' }), #{options.to_json});
|
37
|
+
STRING
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(name, *args)
|
41
|
+
if name.to_s.match(/add_/)
|
42
|
+
type = name.to_s.gsub(/add_/){""}.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
43
|
+
return add_graph(type, *args)
|
44
|
+
else
|
45
|
+
raise NoMethodError.new("Undefined method #{name} for #{self.inspect}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<script type='text/javascript' src='http://www.google.com/jsapi<%= @api_key %>'></script>
|
2
|
+
<script type='text/javascript'>
|
3
|
+
// <![CDATA[
|
4
|
+
google.load('visualization', '1', {'packages':[<%= @viz_package_names.map{|p|"'" + p.downcase + "'"}.join(',') -%>]});
|
5
|
+
google.setOnLoadCallback(drawChart<%= @namespace %>);
|
6
|
+
|
7
|
+
|
8
|
+
function createDataTable(data_pkg, _columns, first_column_title){
|
9
|
+
if(typeof(first_column_title) == undefined) first_column_title = false;
|
10
|
+
var dataTable = new google.visualization.DataTable();
|
11
|
+
var data_columns = data_pkg['columns'];
|
12
|
+
for(var j = 0; j < _columns.length; ++j){
|
13
|
+
if(j == 0 && first_column_title){
|
14
|
+
dataTable.addColumn('string', _columns[j]);
|
15
|
+
}else if(data_columns[_columns[j]] != undefined){
|
16
|
+
dataTable.addColumn(data_columns[_columns[j]], _columns[j]);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
data = data_pkg['data']
|
20
|
+
dataTable.addRows(data.length);
|
21
|
+
for(var i = 0; i < data.length; ++i){
|
22
|
+
for(var j = 0; j < _columns.length; ++j){
|
23
|
+
if(data[i][_columns[j]] != undefined){
|
24
|
+
if(j == 0 && first_column_title){
|
25
|
+
dataTable.setValue(i, j, String(data[i][_columns[j]]));
|
26
|
+
}else{
|
27
|
+
dataTable.setValue(i, j, data[i][_columns[j]]);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
return dataTable;
|
33
|
+
}
|
34
|
+
|
35
|
+
<%- @datas.each do |k, data| -%>
|
36
|
+
var <%= data.data_name %> = <%= data.to_json %>;
|
37
|
+
<%- end -%>
|
38
|
+
|
39
|
+
function drawChart<%= @namespace %>() {
|
40
|
+
<%= @visualizations %>
|
41
|
+
}
|
42
|
+
// ]]>
|
43
|
+
</script>
|
data/lib/g_viz.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html
|
2
|
+
# data.addColumn('date', 'Date');
|
3
|
+
# data.addColumn('number', 'Sold Pencils');
|
4
|
+
# data.addColumn('string', 'title1');
|
5
|
+
# data.addColumn('string', 'text1');
|
6
|
+
# data.addColumn('number', 'Sold Pens');
|
7
|
+
# data.addColumn('string', 'title2');
|
8
|
+
# data.addColumn('string', 'text2');
|
9
|
+
# data.addRows(6);
|
10
|
+
# data.setValue(0, 0, new Date(2008, 1 ,1));
|
11
|
+
# data.setValue(0, 1, 30000);
|
12
|
+
# data.setValue(0, 4, 40645);
|
13
|
+
# data.setValue(1, 0, new Date(2008, 1 ,2));
|
14
|
+
# data.setValue(1, 1, 14045);
|
15
|
+
# data.setValue(1, 4, 20374);
|
16
|
+
# data.setValue(2, 0, new Date(2008, 1 ,3));
|
17
|
+
# data.setValue(2, 1, 55022);
|
18
|
+
# data.setValue(2, 4, 50766);
|
19
|
+
# data.setValue(3, 0, new Date(2008, 1 ,4));
|
20
|
+
# data.setValue(3, 1, 75284);
|
21
|
+
# data.setValue(3, 4, 14334);
|
22
|
+
# data.setValue(3, 5, 'Out of Stock');
|
23
|
+
# data.setValue(3, 6, 'Ran out of stock on pens at 4pm');
|
24
|
+
# data.setValue(4, 0, new Date(2008, 1 ,5));
|
25
|
+
# data.setValue(4, 1, 41476);
|
26
|
+
# data.setValue(4, 2, 'Bought Pens');
|
27
|
+
# data.setValue(4, 3, 'Bought 200k pens');
|
28
|
+
# data.setValue(4, 4, 66467);
|
29
|
+
# data.setValue(5, 0, new Date(2008, 1 ,6));
|
30
|
+
# data.setValue(5, 1, 33322);
|
31
|
+
# data.setValue(5, 4, 39463);
|
32
|
+
mapping = [[:date, 'Date'],[:sold_pencils, 'Solid Pencils'], [:title1, 'title1'], [:text1, 'text1'],
|
33
|
+
[:sold_pens, 'Sold Pens'], [:title2, 'title2'], [:text2, 'text2']]
|
34
|
+
|
35
|
+
data = [
|
36
|
+
{:date => "2008-01-01", :sold_pencils => 30000, :sold_pens => 40645},
|
37
|
+
{:date => Date.parse("2008-01-02"), :sold_pencils => 14045, :sold_pens => 20374},
|
38
|
+
{:date => Date.parse("2008-01-03"), :sold_pencils => 55022, :sold_pens => 50766},
|
39
|
+
{:date => Date.parse("2008-01-04"), :sold_pencils => 75284, :sold_pens => 14334, :title2 => 'Out of Stock',:text2 => 'Ran out of stock on pens at 4pm'},
|
40
|
+
{:date => Date.parse("2008-01-05"), :sold_pencils => 41476, :sold_pens => 66467, :title1 => 'Bought Pens',:text2 => 'Bought 200k pens'},
|
41
|
+
{:date => Date.parse("2008-01-06"), :sold_pencils => 33322, :sold_pens => 39463, :title1 => 'Bought Pens',:text2 => 'Bought 200k pens'}
|
42
|
+
]
|
43
|
+
|
44
|
+
@test_data = [data, mapping]
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
describe GViz do
|
4
|
+
describe 'api' do
|
5
|
+
describe 'examples' do
|
6
|
+
|
7
|
+
describe 'annotated timeline' do
|
8
|
+
@mapping = [[:date, 'Date'],[:sold_pencils, 'Sold Pencils'], [:title1, 'title1'], [:text1, 'text1'],
|
9
|
+
[:sold_pens, 'Sold Pens'], [:title2, 'title2'], [:text2, 'text2']]
|
10
|
+
|
11
|
+
@data = [
|
12
|
+
{:date => "2008-02-01", :sold_pencils => 30000, :sold_pens => 40645},
|
13
|
+
{:date => Date.parse("2008-02-02"), :sold_pencils => 14045, :sold_pens => 20374},
|
14
|
+
{:date => Date.parse("2008-02-03"), :sold_pencils => 55022, :sold_pens => 50766},
|
15
|
+
{:date => Date.parse("2008-02-04"), :sold_pencils => 75284, :sold_pens => 14334, :title2 => 'Out of Stock', :text2 => 'Ran out of stock on pens at 4pm'},
|
16
|
+
{:date => Date.parse("2008-02-05"), :sold_pencils => 41476, :sold_pens => 66467, :title1 => 'Bought Pens', :text1 => 'Bought 200k pens'},
|
17
|
+
{:date => Date.parse("2008-02-06"), :sold_pencils => 33322, :sold_pens => 39463}
|
18
|
+
]
|
19
|
+
g = GViz::Base.new
|
20
|
+
g.add_data(@data, @mapping)
|
21
|
+
g.add_graph('AnnotatedTimeLine', 'chart_id', @data, [:date, :sold_pencils, :tilte1, :text1, :sold_pens, :title2, :text2], {:displayAnnotations => true})
|
22
|
+
output = g.output
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'implementation details - class methods' do
|
29
|
+
describe 'google_data_type' do
|
30
|
+
it "should classify ruby data types to google visualization data types" do
|
31
|
+
GViz::Data.google_data_type(Time.now).should == 'datetime'
|
32
|
+
GViz::Data.google_data_type(Date.new).should == 'date'
|
33
|
+
GViz::Data.google_data_type("June 23 1982").should == 'date'
|
34
|
+
GViz::Data.google_data_type("June 23 1982 12:23").should == 'datetime'
|
35
|
+
GViz::Data.google_data_type("12312412").should == 'number'
|
36
|
+
GViz::Data.google_data_type("12312412.1234").should == 'number'
|
37
|
+
GViz::Data.google_data_type(1234123).should == 'number'
|
38
|
+
GViz::Data.google_data_type(1234123.1234).should == 'number'
|
39
|
+
GViz::Data.google_data_type("a123124123").should == 'string'
|
40
|
+
# should this really happen? documenting it because i need to think if this is ok.
|
41
|
+
GViz::Data.google_data_type("a12312412").should == 'date'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'ruby_to_js' do
|
46
|
+
it "should return the js string representation of that data " do
|
47
|
+
GViz::Data.ruby_to_js('numeric', 12341234).should == 12341234
|
48
|
+
GViz::Data.ruby_to_js('string', 12341234).should == "12341234"
|
49
|
+
GViz::Data.ruby_to_js('date', "June 23 1982").should == Date.parse('June 23 1982')
|
50
|
+
GViz::Data.ruby_to_js('date', Date.parse("June 23 1982")).should == Date.parse('June 23 1982')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'implmentation details - instances methods' do
|
56
|
+
before(:all) do
|
57
|
+
@games = [{:name => "Gary", :games_won => "2", :birthday => "2008-02-01"},
|
58
|
+
{:name => "John", :games_won => "4", :birthday => Date.parse("2009-01-01 11:11")},
|
59
|
+
{:name => "A", :games_won => "2", :birthday => "Jun 14 1982"}]
|
60
|
+
|
61
|
+
@rows = [["'Gary'", "2", "new Date(2008, 1, 1)"],
|
62
|
+
["'John'", "4", "new Date(2009, 0, 1)"],
|
63
|
+
["'A'", "2", "new Date(1982, 5, 14)"]]
|
64
|
+
|
65
|
+
@gviz = GViz::Data.new(@games, [[:name, "Name"], [:games_won, "Games Won"], [:birthday, 'Birthday']])
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'columns' do
|
69
|
+
it 'should return google data types and labels' do
|
70
|
+
@gviz.columns.should == [['string', :name], ['number', :games_won], ['date', :birthday]]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# describe 'rows' do
|
77
|
+
# it 'should return data rows' do
|
78
|
+
# @gviz.rows.should == @rows
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
|
2
|
+
<script type='text/javascript'>
|
3
|
+
google.load('visualization', '1', {'packages':['annotatedtimeline']});
|
4
|
+
google.setOnLoadCallback(drawChart);
|
5
|
+
function drawChart() {
|
6
|
+
var data = new google.visualization.DataTable();
|
7
|
+
data.addColumn('date', 'Date');
|
8
|
+
data.addColumn('number', 'Sold Pencils');
|
9
|
+
data.addColumn('string', 'title1');
|
10
|
+
data.addColumn('string', 'text1');
|
11
|
+
data.addColumn('number', 'Sold Pens');
|
12
|
+
data.addColumn('string', 'title2');
|
13
|
+
data.addColumn('string', 'text2');
|
14
|
+
data.addRows(6);
|
15
|
+
data.setValue(0, 0, new Date(2008, 1 ,1));
|
16
|
+
data.setValue(0, 1, 30000);
|
17
|
+
data.setValue(0, 4, 40645);
|
18
|
+
data.setValue(1, 0, new Date(2008, 1 ,2));
|
19
|
+
data.setValue(1, 1, 14045);
|
20
|
+
data.setValue(1, 4, 20374);
|
21
|
+
data.setValue(2, 0, new Date(2008, 1 ,3));
|
22
|
+
data.setValue(2, 1, 55022);
|
23
|
+
data.setValue(2, 4, 50766);
|
24
|
+
data.setValue(3, 0, new Date(2008, 1 ,4));
|
25
|
+
data.setValue(3, 1, 75284);
|
26
|
+
data.setValue(3, 4, 14334);
|
27
|
+
data.setValue(3, 5, 'Out of Stock');
|
28
|
+
data.setValue(3, 6, 'Ran out of stock on pens at 4pm');
|
29
|
+
data.setValue(4, 0, new Date(2008, 1 ,5));
|
30
|
+
data.setValue(4, 1, 41476);
|
31
|
+
data.setValue(4, 2, 'Bought Pens');
|
32
|
+
data.setValue(4, 3, 'Bought 200k pens');
|
33
|
+
data.setValue(4, 4, 66467);
|
34
|
+
data.setValue(5, 0, new Date(2008, 1 ,6));
|
35
|
+
data.setValue(5, 1, 33322);
|
36
|
+
data.setValue(5, 4, 39463);
|
37
|
+
|
38
|
+
var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
|
39
|
+
chart.draw(data, {displayAnnotations: true});
|
40
|
+
}
|
41
|
+
</script>
|
data/spec/test_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'g_viz')
|
3
|
+
|
4
|
+
class TestHelper
|
5
|
+
def self.template(name)
|
6
|
+
f = File.open(File.join(File.dirname(__FILE__), 'g_viz', 'templates', "#{name}.html"))
|
7
|
+
d = f.readlines(nil)
|
8
|
+
return d[0].to_s
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: JamieFlournoy-g_viz
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gary Tsang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-25 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A Ruby client for the Google Visualization API.
|
17
|
+
email: gary.tsang@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.markdown
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- CHANGELOG
|
27
|
+
- JamieFlournoy-g_viz.gemspec
|
28
|
+
- Manifest
|
29
|
+
- README.markdown
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- lib/g_viz.rb
|
33
|
+
- lib/g_viz/data.rb
|
34
|
+
- lib/g_viz/g_viz.rb
|
35
|
+
- lib/g_viz/json_google.rb
|
36
|
+
- lib/g_viz/templates/data_tables.erb
|
37
|
+
- spec/g_viz/fixtures/annotated_timeline.rb
|
38
|
+
- spec/g_viz/g_viz_spec.rb
|
39
|
+
- spec/g_viz/templates/rendered_annotated_timeline.html
|
40
|
+
- spec/test_helper.rb
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/JamieFlournoy/g_viz
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --charset=UTF-8
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: none
|
65
|
+
rubygems_version: 1.3.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: Google Visualization API Ruby Client
|
69
|
+
test_files:
|
70
|
+
- spec/g_viz/fixtures/annotated_timeline.rb
|
71
|
+
- spec/g_viz/g_viz_spec.rb
|
72
|
+
- spec/test_helper.rb
|