Tom Copeland's Recent Posts

RSS Feeds

« Ruby front end, Ruby on Rails backend | Main | Commit emails and password prompts on RubyForge »

Charts and graphs in Ruby on Rails

Thanks to Geoffrey Grosenbach for writing the great little Gruff graphing library!  It's a fine piece of work and let me create some nice graphs for the indi backend. 

More specifically, I wanted to do some time based graphs.  Here's some code to create a list of crumpets sold to date:

      days = 5
      g = Gruff::Line.new(500)
      g.title = "Crumpets over the past #{days} days"
      g.theme_keynote
      crumpets_to_date = []
      labels = {}
      days.downto(0) do |day|
        date_stamp = Time.now - (60*60*24*day)
        date_sql_string = date_stamp.strftime("%Y-%m-%d")
        crumpets_to_date << Crumpets.count("created_on < '#{date_sql_string}'").to_i
        labels[days-day] = date_stamp.strftime("%b %d") if day % 3 == 0
      end
      g.data("Crumpets Sold", crumpets_to_date)
      g.labels = labels
      send_data(g.to_blob,
:disposition => 'inline',
:type => 'image/png',
:filename => "crumpets_over_time.png")

The graph produced looks like this:

Couple of misc notes:

  • This assumes that the Crumpet object has a Rails created_on field
  • The if day % 3 == 0 just spaces out the date labels a bit
  • This code can go right into a controller and, if you put it in an action called crumpetchartaction, can be called from a view with something like <img src="/controller/crumpetchartaction"/>
  • If you're using Gruff, consider donating a few bucks to Geoffrey for encouragement's sake.  Yup, I did :-)

There are some tricky bits in getting Gruff set up; I've seen posts on the Rails list and elsewhere from folks having problems.  Here are some notes on getting the fonts set up:

  • ImageMagick (or RMagick? not sure) wants to default to the font ariel.ttf.  This didn't come with Fedora Core, but I got it by downloading and installing msttcorefonts-1.2-3.src.rpm
  • Of course, that's just a source RPM, so I cd /usr/src/redhat/SPECS and did a rpmbuild --ba msttcorefonts.spec.
  • Oops, it needs cabextract, so I got that from here; I got the cabextract-1.1-1.i386.rpm file and installed it.
  • Back to /usr/src/redhat/SPECS, running rpmbuild again, but it can't download the fonts from the SourceForge mirror.  Edited the msttcorefonts.spec file, changed the first character of line 10 from a "#" to a "%" - in other words, switched the SourceForge mirror selection from the telia mirror to the umn mirror.  Now the rpmbuild command works fine, it builds the RPM, yay!
  • Now do a rpm -i /usr/src/redhat/RPMS/noarch/msttcorefonts-1.2-3.noarch.rpm, that installs the fonts.  But ImageMagick still couldn't find them, so I did a mkdir /usr/share/fonts/default/TrueType and a cp /usr/X11R6/lib/X11/fonts/msttcoreconts/*.ttf /usr/share/fonts/default/TrueType/.  After that... success!

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83451d3c069e200e5505cda3a8833

Listed below are links to weblogs that reference Charts and graphs in Ruby on Rails:

Comments

Thanks, Tom!

I'm hoping to improve the label spacing so it automatically omits some labels if there are too many to fill the space.

Not at all, thanks to you Geoffrey for such a fine library!

It's ImageMagick that defaults to Arial, if it can find it. But I believe it should be able to find a similar font if Arial isn't available. I don't have any problems running RMagick on OS X with no Arial in sight.

Tim - yeah, it was weird... I couldn't get it going without those fonts. Ah well, once they were installed, all was well.
Hm, looking at that post, I need to update it - I now use a simple GROUP BY query rather than doing 5 separate queries...

Hey, your column seems to cut the code on the right side, in Opera and Firefox, might be the overflow setting.

How would youre query look like with group by? I'm looking for some efficient ways for doing something simliar :)

Hi Christophe - it's more or less this:

--------------
sql = "SELECT to_char(created_on,'MM-DD-YYYY'), COUNT(*) FROM crumpets WHERE created_on > '#{30.days.ago.strftime("%Y-%m-%d")}' GROUP BY to_char(created_on,'MM-DD-YYYY') ORDER BY to_char(created_on,'MM-DD-YYYY')"
rows = ActiveRecord::Base.connection.query(sql)
sorted = rows.sort {|a,b| DateTime.strptime(a[0], "%m-%d-%Y") DateTime.strptime(b[0], "%m-%d-%Y")}
sorted.each_with_index do |rec, index|
crumpets_per_day << rec[1].to_i
g.labels[index] = DateTime.strptime(rec[0], "%m-%d-%Y").strftime("%b %d") if index % 10 == 0
end
--------------

The formatting is lousy, but, you get the idea - the GROUP BY is done on a truncated version of the created_on date, and so only one query needs to be done.

Hello,

Just thought I'd ask if anyone could wrap this flash graph in Ruby? It has a PHP wrapper so it should be quite easy.

http://teethgrinder.co.uk/open-flash-chart/

thanks.

monk.e.boy

monk-e-boy - hm, you might want to post a note to the Rails list and see if anyone's done that already...

Nice tutorial, but that's a lot of crumpets. :-)

I think that Gruff rocks! I am really impressed with how easy it is to use and produce great looking charts.

Check out this simple little app I built that uses Rails, Rmagick/Gruff.

http://www.homeloancalculator.com.au

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been saved. Comments are moderated and will not appear until approved by the author. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Comments are moderated, and will not appear until the author has approved them.