Google Charts in Rails, gchartrb

This week I was playing around with Google Charts, a wonderful API for creating charts via a URL. While I developed a helper class to create charts more easily in Rails, I did a little research and realized the RubyGem gchartrb has a great API for creating these charts. Here's a quick tutorial on using gchartrb from the ground up.

Installing gchartrb

To install gchartrb, simply use the command gem install gchartrb from your command prompt. Check out these instructions for additional help and to access the gchartrb packages (Downloadable here).

Quick Examples

Now that we have our gem installed, we can create graphs right away. First, remember to require the gem at the top of your code. Notice how the gchartrb gem is actually called "google_chart":

require 'rubygems'
require 'google_chart'

There are a couple ways that you can create a chart. You can instantiate the graph and then add attributes to it:

lc = GoogleChart::LineChart.new("400x200", "My Results", false)

Alternatively, you can create the graph and add the attributes within a block:

GoogleChart::LineChart.new("400x200", "My Results", false) do |lc|
  # Put lc data here
  # ...
  puts lc.to_url
end

I personally prefer the latter method, as the creation of the graph and its attributes are kept together in a modular fashion.

Here are some examples of line, bar, and pie charts:

Line Chart

lc = GoogleChart::LineChart.new("400x200", "My Results", false)
lc.data "Line green", [3,5,1,9,0,2], '00ff00'
lc.data "Line red", [2,4,0,6,9,3], 'ff0000'
lc.axis :y, :range => [0,10], :font_size => 10, :alignment => :center
lc.show_legend = false
lc.shape_marker :circle, :color => '0000ff', :data_set_index => 0, :data_point_index => -1, :pixel_size => 10
puts lc.to_url

Notice that each lc.data call will create a new data line for you. The second parameter accepts a integer or float array, which can be anything you like. Lets say you have a WeighIn model that has weight as an attribute and belongs to some Person. If a person weighs himself/herself once a month for a year, then we can collect that data and show your trend via a line graph. Collecting that data and using it would look like this:

# In the controller Person
def show
  @person = Person.find(params[:id])
  weigh_ins = @person.weigh_ins.collect(&:weight)

  lc = GoogleChart::LineChart.new("#{width}x200", "My Results", false)
  lc.data "Weigh ins", weigh_ins, green

  # etc, etc...

  puts lc.to_url # Or @line_graph = lc.to_url
end

Another useful function, lc.axis, can be used to specify your own data range labels, but it is not required to create a chart (default ranges and labels will be used). The last function, lc.to_url, takes the information specified for the line chart and puts it into the Google charts url.

Bar Chart

bar_1_data = [350,110,700]
bar_2_data = [200,800,50]
color_1 = 'c53711'
color_2 = '0000ff'
names_array = ["Bob","Stella","Foo"]
GoogleChart::BarChart.new("600x300", "Horizontal Bar Graph", :horizontal, false) do |bc|
  bc.data "FirstResultBar", bar_1_data, color_1
  bc.data "SecondResultBar", bar_2_data, color_2
  bc.axis :y, :labels => names_array, :font_size => 10
  bc.axis :x, :range => [0,1000]
  bc.show_legend = false
  bc.stacked = true
  bc.data_encoding = :extended
  bc.shape_marker :circle, :color => '00ff00', :data_set_index => 0, :data_point_index => -1, :pixel_size => 10
  puts bc.to_url
end

An interesting attribute to pay attention to is bc.stacked, which gives you the ability to stack bar data, or to create separate bars together. When bc.stacked = false, the chart above is what is shown.

If bc.stacked = true, the same data will look like this:

Also, if you wanted to use this code in one of your controllers, and then display the graph in a template (view) file, you would set the graph's url in the controller: @graph = bc.to_url Then within the view, you can simple show the graph as an image like this:

<!-- From within the view file --> 
<img src="<%= @graph %>"/> 

Pie Chart

GoogleChart::PieChart.new('320x200', "Pie Chart",false) do |pc| 
  pc.data "Apples", 40 
  pc.data "Banana", 20 
  pc.data "Peach", 30 
  pc.data "Orange", 60 
  puts "\nPie Chart" 
  puts pc.to_url 
  # Pie Chart with no labels 
  pc.show_labels = false 
  puts "\nPie Chart (with no labels)" 
  puts pc.to_url 
end

This last example was taken from gchartrb's readme file, which has an example for each kind of chart you can create (including Venn diagrams, Scatter charts, XY Line charts, etc). Notice that the data does not need to be within 0 to 100 (like percents on the pie chart) - the data will be added together and scaled appropriately by gchartrb. If you want to make the chart 3d, either set the 3rd parameter on PieChart.new to true, or you can set the attribute manually: pc.is_3d = true

Useful parameters

Google charts, by default, works with the data range between 0 and 100. Most of the time, your values will not work with this same scale. Instead of converting your data to the default scale, you can specify the data range with the :range parameter in bc.axis. So if you data was between 1 and 12 on the x_axis (like months in a year), then you could specify that range like so:

lc.axis :x, :range =&gt; [1,12], :labels =&gt; month_names_array

If you're working with large data sets/numbers, then you may have chart data that is slightly off the mark. The default encoding that gchartrb uses is called Simple Encoding, which only has 62 points of resolution. We can easily expand this resolution (to 4096 points of resolution) by using Extended encoding, which a chart can select by changing the data_encoding attribute with :extended. For a line graph lc, it would look like this: lc.data_encoding = :extended . See Chart data for an explanation for all the encodings Google charts uses.

gchartrb subtlities

While gchartrb provides a great API for create charts in Rails, there are some subtle details about gcharts that you should be aware of. First of all, all charts derive from the base class GoogleChart::Base - check it out to see all the methods and attributes that apply to all charts. Secondly, gchartrb encodes all of the data values in some_chart.data from numeric form into a string representation of the data. This conversion doesn't effect the final output of your chart, and helps make the chart url shorter in length. Again, if your working with large values, make sure the use the extended coding by using lc.data_encoding :extended.

Other Resources

Now that you have a taste of Google Charts with gchartrb, check out the API documentation here. If gchartrb doesn't suit your tastes, you can go directly to the Google Charts API - it is thorough and self-explanatory. Ajaxian shows a number of quick examples of Google Charts here, and Matthew Bass gives a solid introduction to Google Charts and a few examples with gchartrb here. Lastly, here is a great link for 50 Cool Things You Can Do with Google Charts.