views:

354

answers:

2

I am using the googlecharts gem in my rails app for some simple charting. It works beautifully, except my app is required to be SSL encrypted at all times. In order to pull the google charts, the charts gem of course makes an http request to google which leads to a browser warning about some insecure content on the page for most users. Has anyone else faced this issue and devised a solution to avoid the warning? I am afraid I will need to figure out a way to make the http call, store the image google returns locally, and then display that in the app but figured someone else has already found a nice way to handle this.

A: 

I don't know of an existing plugin that will do this, but you can do it on your own. Simply write a new controller method that will get the chart via HTTP and then return it immediately (no need to save it to a file)

In controller:

require 'net/http'
def googlechart
  send_data Net::HTTP.get("http://chart.apis.google.com/chart?#{params[:api]}"),
    :content_type => 'image/png',
    :disposition  => 'inline'
end

In view:

<%= image_tag googlechart_path(:api=>'cht=p&chd=s:Uf9a&chs=200x100&chl=January') %>

Just set up your route and you're all set.

Drew Blas
Net::HTTP.get won't work with a string as the argument. It needs to be an instance of URI::HTTP or a similiar object that responds to host.
Steve Graham
+1  A: 

The API Google Charts API endpoint is stored in the class variable @@url inside the Gchart class. So initially I thought of monkeypatching the class variable to set the url to https

# Put this in an initializer
Gchart.send :class_variable_set, :@@url, "https://chart.apis.google.com/chart?"

alas Google Charts does not work via https. So we can't use that method. As the Gchart class methods just return a URL we can wrap the calls up in a proxy controller method that does the API call server side and proxies it to the client via the ActionController send_data method using your protocol of choice. That way you don't have to reinvent the Gchart library wheel.

class ChartsController < ApplicationController
  require 'net/http'
  require 'gchart'

  def show
    options = params.except :controller, :action
    options[:data].map! { |x| x.to_i } unless options[:data].nil?
    begin 
      chart = URI.parse(Gchart.send options.delete(:type), options)
      send_data Net::HTTP.get(chart), :content_type => 'image/png', :disposition  => 'inline'
    rescue
      raise ActiveRecord::RecordNotFound
    end
  end

end

The helper you can use in your views:

module ApplicationHelper

  def chart_tag(options ={})
    image_tag chart_path(options)
  end

end

and the route

map.resource :chart, :only => :show

Usage:

<%= chart_tag :type => "line", :size => '200x300', :title => "example title", :bg => 'efefef', :legend => ['first data set label', 'second data set label'], :data => [10, 30, 120, 45, 72] %>

Code is untested but should give you a good start.

Steve Graham
Sorry for the slow response, but this works perfect. Very well done.
Dan
you're welcome dude.
Steve Graham