rgviz-rails 0.67 → 0.68
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.
- data/README.markdown +135 -0
- data/lib/rgviz_rails/executor.rb +28 -1
- data/lib/rgviz_rails/init.rb +2 -2
- data/lib/rgviz_rails/parser.rb +2 -2
- data/lib/rgviz_rails/view_helper.rb +11 -7
- metadata +9 -9
- data/README.rdoc +0 -131
data/README.markdown
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
rgviz-rails
|
2
|
+
===========
|
3
|
+
|
4
|
+
this library makes it easy to implement a visualization data source so that you can easily chart or visualize your data from [activerecord](http://ar.rubyonrails.org/) models or from in-memory arrays. the library implements the [google visualization api wire protocol](http://code.google.com/apis/visualization/documentation/dev/implementing_data_source.html).
|
5
|
+
|
6
|
+
it also allows you to [render the visualizations in a view template](https://github.com/asterite/rgviz-rails/wiki/showing-a-visualization-in-a-view) in a very simple but powerful way.
|
7
|
+
|
8
|
+
this library is built on top of [rgviz](https://github.com/asterite/rgviz).
|
9
|
+
|
10
|
+
installation
|
11
|
+
------------
|
12
|
+
|
13
|
+
gem install rgviz-rails
|
14
|
+
|
15
|
+
rails 3
|
16
|
+
-------
|
17
|
+
|
18
|
+
in your gemfile
|
19
|
+
|
20
|
+
gem 'rgviz'
|
21
|
+
gem 'rgviz-rails', :require => 'rgviz_rails'
|
22
|
+
|
23
|
+
rails 2.x
|
24
|
+
---------
|
25
|
+
|
26
|
+
in your environment.rb
|
27
|
+
|
28
|
+
config.gem "rgviz"
|
29
|
+
config.gem "rgviz-rails", :lib => 'rgviz_rails'
|
30
|
+
|
31
|
+
usage
|
32
|
+
-----
|
33
|
+
|
34
|
+
to make a method in your controller be a visualization api endpoint:
|
35
|
+
|
36
|
+
class vizcontroller < applicationcontroller
|
37
|
+
def person
|
38
|
+
# person is an activerecord::base class
|
39
|
+
render :rgviz => person
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
so for example if <tt>person</tt> has <tt>name</tt> and <tt>age</tt>, pointing your browser to:
|
44
|
+
|
45
|
+
http://localhost:3000/viz/person?select name where age > 20 limit 5
|
46
|
+
|
47
|
+
would render the necessary javascript code that implements the google visualization api wire protocol.
|
48
|
+
|
49
|
+
associations
|
50
|
+
------------
|
51
|
+
|
52
|
+
if you want to filter, order by or group by columns that are in a model's association you can use underscores. this is better understood with an example:
|
53
|
+
|
54
|
+
class person < activerecord::base
|
55
|
+
belongs_to :city
|
56
|
+
end
|
57
|
+
|
58
|
+
class city < activerecord::base
|
59
|
+
belongs_to :country
|
60
|
+
end
|
61
|
+
|
62
|
+
class country < activerecord::base
|
63
|
+
end
|
64
|
+
|
65
|
+
to select the name of the city each person belongs to:
|
66
|
+
|
67
|
+
select city_name
|
68
|
+
|
69
|
+
to select the name of the country of the city each person belongs to:
|
70
|
+
|
71
|
+
select city_country_name
|
72
|
+
|
73
|
+
a slightly more complex example:
|
74
|
+
|
75
|
+
select avg(age) where city_country_name = 'argentina' group by city_name
|
76
|
+
|
77
|
+
the library will make it in just one query, writing all the sql joins for you.
|
78
|
+
|
79
|
+
extra conditions
|
80
|
+
----------------
|
81
|
+
|
82
|
+
sometimes you want to limit your results the query will work with. you can do it like this:
|
83
|
+
|
84
|
+
render :rgviz => person, :conditions => ['age > ?', 20]
|
85
|
+
|
86
|
+
or also:
|
87
|
+
|
88
|
+
render :rgviz => person, :conditions => 'age > 20'
|
89
|
+
|
90
|
+
preprocessing
|
91
|
+
-------------
|
92
|
+
|
93
|
+
if you need to tweak a result before returning it, just include a block:
|
94
|
+
|
95
|
+
render :rgviz => person do |table|
|
96
|
+
# modify the rgviz::table object
|
97
|
+
end
|
98
|
+
|
99
|
+
showing a visualization in a view
|
100
|
+
---------------------------------
|
101
|
+
|
102
|
+
you can invoke the rgviz method in your views. [read more about this](https://github.com/asterite/rgviz-rails/wiki/showing-a-visualization-in-a-view).
|
103
|
+
|
104
|
+
you can always do it the [old way](http://code.google.com/apis/visualization/documentation/using_overview.html).
|
105
|
+
|
106
|
+
executing queries over in-memory arrays
|
107
|
+
---------------------------------------
|
108
|
+
|
109
|
+
you can also apply a query over an array of arrays that contains your "records" to be queried.
|
110
|
+
|
111
|
+
types = [[:id, :number], [:name, :string], [:age, :number]]
|
112
|
+
records = [
|
113
|
+
[1, 'john', 23],
|
114
|
+
[2, 'pete', 36]
|
115
|
+
]
|
116
|
+
executor = rgviz::memoryexecutor.new records, types
|
117
|
+
|
118
|
+
render :rgviz => executor
|
119
|
+
|
120
|
+
this is very useful if you need to present visualizations against data coming from a csv file.
|
121
|
+
|
122
|
+
current limitations
|
123
|
+
-------------------
|
124
|
+
|
125
|
+
* the *format* clause works, but formatting is as in ruby (like "%.2f" for numbers, "foo %s bar" for strings, and "%y-%m-%d" for dates, as specified by time#strftime)
|
126
|
+
* only supports mysql, postgresql and sqlite adapters
|
127
|
+
* these scalar functions are not supported for sqlite: *millisecond*, *quarter*
|
128
|
+
* these scalar functions are not supported for mysql: *millisecond*
|
129
|
+
* the function *toDate* doesn't accept a number as its argument
|
130
|
+
* the *tsv* output format is not supported
|
131
|
+
|
132
|
+
contributors
|
133
|
+
------------
|
134
|
+
|
135
|
+
* [brad seefeld](https://github.com/bradseefeld)
|
data/lib/rgviz_rails/executor.rb
CHANGED
@@ -2,6 +2,7 @@ module Rgviz
|
|
2
2
|
class Executor
|
3
3
|
attr_reader :model_class
|
4
4
|
attr_reader :adapter
|
5
|
+
attr_reader :virtual_columns
|
5
6
|
|
6
7
|
def initialize(model_class)
|
7
8
|
@model_class = model_class
|
@@ -27,11 +28,13 @@ module Rgviz
|
|
27
28
|
|
28
29
|
def execute(query, options = {})
|
29
30
|
@query = query
|
30
|
-
@query = RgvizRails::Parser.parse(@query
|
31
|
+
@query = RgvizRails::Parser.parse(@query) unless @query.kind_of?(Query)
|
31
32
|
|
32
33
|
@table = Table.new
|
33
34
|
@extra_conditions = options[:conditions]
|
35
|
+
@virtual_columns = options[:virtual_columns]
|
34
36
|
|
37
|
+
process_virtual_columns
|
35
38
|
process_pivot
|
36
39
|
process_labels
|
37
40
|
process_formats
|
@@ -46,6 +49,17 @@ module Rgviz
|
|
46
49
|
@table
|
47
50
|
end
|
48
51
|
|
52
|
+
def process_virtual_columns
|
53
|
+
return unless @virtual_columns
|
54
|
+
|
55
|
+
@virtual_columns.each do |key, value|
|
56
|
+
if value.is_a?(String) || value[:gql]
|
57
|
+
parser = RgvizRails::Parser.new(value.is_a?(String) ? value : value[:gql])
|
58
|
+
@virtual_columns[key] = {:gql => parser.parse_column}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
49
63
|
def process_labels
|
50
64
|
return unless @query.labels.present?
|
51
65
|
|
@@ -319,6 +333,10 @@ module Rgviz
|
|
319
333
|
def column_type(col)
|
320
334
|
case col
|
321
335
|
when IdColumn
|
336
|
+
if @virtual_columns && (vc = @virtual_columns[col.name])
|
337
|
+
return vc[:gql] ? column_type(vc[:gql]) : vc[:type]
|
338
|
+
end
|
339
|
+
|
322
340
|
klass, rails_col, joins = Rgviz::find_rails_col @model_class, col.name
|
323
341
|
raise "Unknown column #{col}" unless rails_col
|
324
342
|
rails_column_type rails_col
|
@@ -440,6 +458,15 @@ module Rgviz
|
|
440
458
|
end
|
441
459
|
|
442
460
|
def visit_id_column(node)
|
461
|
+
if @executor.virtual_columns && (vc = @executor.virtual_columns[node.name])
|
462
|
+
if vc[:gql]
|
463
|
+
vc[:gql].accept self
|
464
|
+
else
|
465
|
+
@string += vc[:sql]
|
466
|
+
end
|
467
|
+
return
|
468
|
+
end
|
469
|
+
|
443
470
|
klass, rails_col, joins = Rgviz::find_rails_col @executor.model_class, node.name
|
444
471
|
raise "Unknown column '#{node.name}'" unless rails_col
|
445
472
|
@string += ActiveRecord::Base.connection.quote_column_name(klass.table_name)
|
data/lib/rgviz_rails/init.rb
CHANGED
@@ -13,7 +13,7 @@ module Rgviz
|
|
13
13
|
else
|
14
14
|
model = hash[:rgviz]
|
15
15
|
conditions = hash[:conditions]
|
16
|
-
|
16
|
+
virtual_columns = hash[:virtual_columns]
|
17
17
|
query = params[:tq] || 'select *'
|
18
18
|
tqx = params[:tqx] || ''
|
19
19
|
|
@@ -22,7 +22,7 @@ module Rgviz
|
|
22
22
|
begin
|
23
23
|
options = {}
|
24
24
|
options[:conditions] = conditions if conditions
|
25
|
-
options[:
|
25
|
+
options[:virtual_columns] = virtual_columns if virtual_columns
|
26
26
|
|
27
27
|
table = if model.is_a?(Class) && model < ActiveRecord::Base
|
28
28
|
Rgviz::Executor.new(model).execute query, options
|
data/lib/rgviz_rails/parser.rb
CHANGED
@@ -20,14 +20,18 @@ module Rgviz
|
|
20
20
|
events = options[:events] || {}
|
21
21
|
html = options[:html] || {}
|
22
22
|
hidden = options[:hidden]
|
23
|
-
extensions = options[:extensions]
|
24
23
|
conditions = options[:conditions]
|
24
|
+
virtual_columns = options[:virtual_columns]
|
25
25
|
package = options[:package]
|
26
26
|
|
27
27
|
rgviz_events, google_events = events.partition{|x| x[0].to_s.start_with? 'rgviz'}
|
28
28
|
rgviz_events = rgviz_events.inject(Hash.new){|h, y| h[y[0]] = y[1]; h}
|
29
29
|
rgviz_events = rgviz_events.with_indifferent_access
|
30
30
|
|
31
|
+
ajax = options.has_key?(:ajax) && options[:ajax]
|
32
|
+
load_package = !ajax && (!options.has_key?(:load_package) || options[:load_package])
|
33
|
+
load_google = !ajax && (!options.has_key?(:load_google) || options[:load_google])
|
34
|
+
|
31
35
|
html_prefix = (options[:html_prefix] || 'html').to_s
|
32
36
|
js_prefix = (options[:js_prefix] || 'js').to_s
|
33
37
|
param_prefix = (options[:param_prefix] || 'param').to_s
|
@@ -87,7 +91,7 @@ module Rgviz
|
|
87
91
|
url = url_for url unless custom_executor
|
88
92
|
|
89
93
|
# Parse the query
|
90
|
-
query = RgvizRails::Parser.parse query
|
94
|
+
query = RgvizRails::Parser.parse query
|
91
95
|
|
92
96
|
# And replace the html_ and javascript_ magic names
|
93
97
|
query.accept visitor
|
@@ -104,7 +108,7 @@ module Rgviz
|
|
104
108
|
|
105
109
|
# Output the google jsapi tag the first time
|
106
110
|
@first_time ||= 1
|
107
|
-
if @first_time == 1
|
111
|
+
if load_google && @first_time == 1
|
108
112
|
out << "<script type=\"text/javascript\" src=\"http://www.google.com/jsapi\"></script>\n"
|
109
113
|
end
|
110
114
|
# Now the real script
|
@@ -150,7 +154,7 @@ module Rgviz
|
|
150
154
|
@defined_rgviz_append = true
|
151
155
|
end
|
152
156
|
|
153
|
-
if
|
157
|
+
if load_package
|
154
158
|
# Load visualizations and the package, if not already loaded
|
155
159
|
package ||= get_package(kind)
|
156
160
|
|
@@ -165,7 +169,7 @@ module Rgviz
|
|
165
169
|
|
166
170
|
# Set the callback if the function doesn't have params and if the
|
167
171
|
# user didn't request to hide the visualization
|
168
|
-
if !hidden && params.empty?
|
172
|
+
if !ajax && !hidden && params.empty?
|
169
173
|
out << "google.setOnLoadCallback(#{callback});\n"
|
170
174
|
end
|
171
175
|
|
@@ -194,7 +198,7 @@ module Rgviz
|
|
194
198
|
else
|
195
199
|
executor_options = {}
|
196
200
|
executor_options[:conditions] = conditions if conditions
|
197
|
-
executor_options[:
|
201
|
+
executor_options[:virtual_columns] = virtual_columns if virtual_columns
|
198
202
|
|
199
203
|
table = if url.is_a?(Class) and url < ActiveRecord::Base
|
200
204
|
Rgviz::Executor.new(url).execute(query, executor_options)
|
@@ -216,7 +220,7 @@ module Rgviz
|
|
216
220
|
out << "});\n"
|
217
221
|
end
|
218
222
|
out << "}\n"
|
219
|
-
|
223
|
+
out << "#{callback}()" if ajax
|
220
224
|
out << "</script>\n"
|
221
225
|
|
222
226
|
# Write the div
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgviz-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.68'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-23 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rgviz
|
16
|
-
requirement: &
|
16
|
+
requirement: &70314626649780 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '0.
|
21
|
+
version: '0.46'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70314626649780
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rails
|
27
|
-
requirement: &
|
27
|
+
requirement: &70314626649300 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,13 +32,13 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70314626649300
|
36
36
|
description:
|
37
37
|
email: aborenszweig@manas.com.ar
|
38
38
|
executables: []
|
39
39
|
extensions: []
|
40
40
|
extra_rdoc_files:
|
41
|
-
- README.
|
41
|
+
- README.markdown
|
42
42
|
files:
|
43
43
|
- lib/rgviz_rails.rb
|
44
44
|
- lib/rgviz_rails/executor.rb
|
@@ -51,7 +51,7 @@ files:
|
|
51
51
|
- lib/rgviz_rails/adapters/sqlite_adapter.rb
|
52
52
|
- lib/rgviz_rails/init.rb
|
53
53
|
- rails/init.rb
|
54
|
-
- README.
|
54
|
+
- README.markdown
|
55
55
|
homepage: http://github.com/asterite/rgviz-rails
|
56
56
|
licenses: []
|
57
57
|
post_install_message:
|
data/README.rdoc
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
== Rgviz-rails
|
2
|
-
|
3
|
-
This library makes it easy to implement a Visualization data source so that you can easily chart or visualize your data from ActiveRecord[http://ar.rubyonrails.org/] models or from in-memory arrays. The library implements the {Google Visualization API wire protocol}[http://code.google.com/apis/visualization/documentation/dev/implementing_data_source.html].
|
4
|
-
|
5
|
-
It also allows you to {render the visualizations in a view template}[https://github.com/asterite/rgviz-rails/wiki/Showing-a-visualization-in-a-view] in a very simple but powerful way.
|
6
|
-
|
7
|
-
This library is built on top of rgviz[https://github.com/asterite/rgviz].
|
8
|
-
|
9
|
-
=== Installation
|
10
|
-
|
11
|
-
gem install rgviz-rails
|
12
|
-
|
13
|
-
=== Rails 3
|
14
|
-
|
15
|
-
In your Gemfile
|
16
|
-
|
17
|
-
gem 'rgviz'
|
18
|
-
gem 'rgviz-rails', :require => 'rgviz_rails'
|
19
|
-
|
20
|
-
=== Rails 2.x
|
21
|
-
|
22
|
-
In your environment.rb
|
23
|
-
|
24
|
-
config.gem "rgviz"
|
25
|
-
config.gem "rgviz-rails", :lib => 'rgviz_rails'
|
26
|
-
|
27
|
-
=== Usage
|
28
|
-
|
29
|
-
To make a method in your controller be a visualization API endpoint:
|
30
|
-
|
31
|
-
class VizController < ApplicationController
|
32
|
-
|
33
|
-
def person
|
34
|
-
# Person is an ActiveRecord::Base class
|
35
|
-
render :rgviz => Person
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
So for example if +Person+ has +name+ and +age+, pointing your browser to:
|
41
|
-
|
42
|
-
http://localhost:3000/viz/person?select name where age > 20 limit 5
|
43
|
-
|
44
|
-
would render the necessary javascript code that implements the Google Visualization API wire protocol.
|
45
|
-
|
46
|
-
=== Extensions
|
47
|
-
|
48
|
-
To enable the extensions defined by rgviz you need to specify it in the render method:
|
49
|
-
|
50
|
-
render :rgviz => Person, :extensions => true
|
51
|
-
|
52
|
-
=== Associations
|
53
|
-
|
54
|
-
If you want to filter, order by or group by columns that are in a model's association you can use underscores. This is better understood with an example:
|
55
|
-
|
56
|
-
class Person < ActiveRecord::Base
|
57
|
-
belongs_to :city
|
58
|
-
end
|
59
|
-
|
60
|
-
class City < ActiveRecord::Base
|
61
|
-
belongs_to :country
|
62
|
-
end
|
63
|
-
|
64
|
-
class Country < ActiveRecord::Base
|
65
|
-
end
|
66
|
-
|
67
|
-
To select the name of the city each person belongs to:
|
68
|
-
|
69
|
-
select city_name
|
70
|
-
|
71
|
-
To select the name of the country of the city each person belongs to:
|
72
|
-
|
73
|
-
select city_country_name
|
74
|
-
|
75
|
-
A slightly more complex example:
|
76
|
-
|
77
|
-
select avg(age) where city_country_name = 'Argentina' group by city_name
|
78
|
-
|
79
|
-
The library will make it in just one query, writing all the SQL joins for you.
|
80
|
-
|
81
|
-
=== Extra conditions
|
82
|
-
|
83
|
-
Sometimes you want to limit your results the query will work with. You can do it like this:
|
84
|
-
|
85
|
-
render :rgviz => Person, :conditions => ['age > ?', 20]
|
86
|
-
|
87
|
-
Or also:
|
88
|
-
|
89
|
-
render :rgviz => Person, :conditions => 'age > 20'
|
90
|
-
|
91
|
-
=== Preprocessing
|
92
|
-
|
93
|
-
If you need to tweak a result before returning it, just include a block:
|
94
|
-
|
95
|
-
render :rgviz => Person do |table|
|
96
|
-
# Modify the Rgviz::Table object
|
97
|
-
end
|
98
|
-
|
99
|
-
=== Showing a visualization in a view
|
100
|
-
|
101
|
-
You can invoke the rgviz method in your views. {Read more about this}[https://github.com/asterite/rgviz-rails/wiki/Showing-a-visualization-in-a-view].
|
102
|
-
|
103
|
-
You can always do it the {old way}[http://code.google.com/apis/visualization/documentation/using_overview.html].
|
104
|
-
|
105
|
-
=== Executing queries over in-memory arrays
|
106
|
-
|
107
|
-
You can also apply a query over an array of arrays that contains your "records" to be queried.
|
108
|
-
|
109
|
-
types = [[:id, :number], [:name, :string], [:age, :number]]
|
110
|
-
records = [
|
111
|
-
[1, 'John', 23],
|
112
|
-
[2, 'Pete', 36]
|
113
|
-
]
|
114
|
-
executor = Rgviz::MemoryExecutor.new records, types
|
115
|
-
|
116
|
-
render :rgviz => executor
|
117
|
-
|
118
|
-
This is very useful if you need to present visualizations against data coming from a CSV file.
|
119
|
-
|
120
|
-
=== Current Limitations
|
121
|
-
|
122
|
-
* The *format* clause works, but formatting is as in ruby (like "%.2f" for numbers, "foo %s bar" for strings, and "%Y-%m-%d" for dates, as specified by Time#strftime)
|
123
|
-
* Only supports MySQL, PostgreSQL and SQLite adapters
|
124
|
-
* These scalar functions are not supported for SQLite: *millisecond*, *quarter*
|
125
|
-
* These scalar functions are not supported for MySQL: *millisecond*
|
126
|
-
* The function *toDate* doesn't accept a number as its argument
|
127
|
-
* The *tsv* output format is not supported
|
128
|
-
|
129
|
-
=== Contributors
|
130
|
-
|
131
|
-
* {Brad Seefeld}[https://github.com/bradseefeld]
|