rgviz-rails 0.67 → 0.68

Sign up to get free protection for your applications and to get access to all the features.
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)
@@ -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, options) unless @query.kind_of?(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)
@@ -13,7 +13,7 @@ module Rgviz
13
13
  else
14
14
  model = hash[:rgviz]
15
15
  conditions = hash[:conditions]
16
- extensions = hash[:extensions]
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[:extensions] = extensions if extensions
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
@@ -1,7 +1,7 @@
1
1
  module RgvizRails
2
2
  class Parser < Rgviz::Parser
3
- def self.parse(string, options = {})
4
- new(string, options).parse
3
+ def self.parse(string)
4
+ new(string).parse
5
5
  end
6
6
 
7
7
  protected
@@ -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, :extensions => extensions
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 !options.has_key?(:load_package) || options[:load_package]
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[:extensions] = extensions if extensions
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.67'
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-04-05 00:00:00.000000000Z
12
+ date: 2012-07-23 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgviz
16
- requirement: &70182476133340 !ruby/object:Gem::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.43'
21
+ version: '0.46'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70182476133340
24
+ version_requirements: *70314626649780
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &70182476132920 !ruby/object:Gem::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: *70182476132920
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.rdoc
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.rdoc
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]