Utilizing the Google Visualization API with Ruby on Rails

If you haven’t seen it yet, Google have recently released a public visualization API for generating many different types of graphs including Geo Map, and Motion Charts. The graphs are all in the nice clean style that you see in Google Analytics. The end result of the graphs is really nice, and is produced with nothing more than javascript, however anyone utilizing a framework for dynamic Web applications will likely want a more developer friendly way to embed the data.

For those of you using Ruby on Rails, I’ve written a plugin gvis that makes the syntax for embedding data a lot cleaner, and most of all, accepts ruby data arrays, handling the library loading and javascript data formatting for you. As an example to see how easy this is, lets go through setting up a new rails application and drawing a graph with this plugin.

rails graphapp
cd graphapp
script/plugin install git://github.com/jeremyolliver/gvis.git
# note you'll need git installed for the above line to work.

Now lets add a single controller and add routes for it.

script/generate controller home

# config/routes.rb
map.resources :home

# include the plugin module in application helper
# so that we can add a graph anywhere in our app

# app/helpers/application_helper.rb
include GoogleVisualization

# Lets add a simple layout, it need only include google's javascript
# source for the visualization api, and then call render_visualizations

# app/views/layouts/application.html.erb
<html>
  <head>
    <title>Test app</title>
    <%= include_visualization_api %>
    <%= render_visualizations %>
    <%= yield :head %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

Now lets render a nice fancy MotionChart on our home page.

# app/views/home/index.html.erb
<h1>Rendering a cool MotionChart</h1>

<%# This data would typically be pulled from the database,
    but lets just put some sample data into an array %>
<% chart_data = [
   ["Apples", Date.new(1998,1,1), 1000,300,'East'],
   ["Oranges", Date.new(1998,1,1), 950,200,'West'],
   ["Bananas", Date.new(1998,1,1), 300,250,'West'],
   ["Apples", Date.new(1998,2,1), 1200,400,'East'],
   ["Oranges", Date.new(1998,2,1), 950,150,'West'],
   ["Bananas", Date.new(1998,2,1), 788,617,'West']
 ] %>

<% visualization "chart_id", "MotionChart", :width => 600, :height => 400,
                             :html => {:class => "graph_class"} do |chart| %>
 <% chart.string "Fruit" %>
 <% chart.date "Date" %>
 <% chart.number "Sales" %>
 <% chart.number "Expenses" %>
 <% chart.string "Location" %>

 <% chart.add_rows(chart_data) %>
<% end %>

And VĂ³ila! we now have a beautiful Motion Chart displayed in our rails app in almost no time. Let me know if you find this useful, or you have any thoughts on how this could be improved.

Custom Change Messages – Rails Plugin

While working on some code maintenance for PlanHQ I noticed a prime opportunity to refactor some code in the spirit of keeping the code DRY. There was code in both the controller action and in mailer methods that created a short paragraph of text describing what fields had been edited on several models for the purposes of both logging this for users to reference later, and to send email notifications.

My solution for this problem was to create this plugin (code available on github) which extends ActiveRecord::Base to provide a few simple methods on instances of your models to generate this text summary of the changes, before the model is saved back to the database (taking advantage of the code in the ActiveRecord::Dirty module). The plugin provides an easy way to customise the messages that are displayed and their format, and handles belongs_to associations nicely as well: Given a Task model that belongs_to a User model, re-assigning a task would produce the message “user has been changed from ‘Jeremy’ to ‘Jordan’” rather than the less informative “user_id has changed from 1 to 2″. See the README for more details on usage.

Usage: see the README for more

# Item.rb
class Item < ActiveRecord::Base
  belongs_to :person

  custom_message_for :person, :display => :username
  custom_message_for :due_on, :as => "Due Date",
  :message => "has been rescheduled", :format => :pretty_print_date

  # this method is used for formatting the due_on field when it changes
  def pretty_print_date(value = self.due_on)
    value.strftime("%d/%m/%Y")
  end
end
# ItemsController.rb
class ItemsController < ApplicationController

  def update
    @item.attributes = params[:item]
    Mailer.deliver_item_update(@item, @item.change_messages.to_sentence)
    @item.save!
  end

end
Follow

Get every new post delivered to your Inbox.