x
11224742 10207744386832061 1134591581572583218 n

Including charts in a RoR3 application

over 6 years ago by Alex
Tags: charts
Popup

Quite often, in pretty much any field, you can end up with large amounts of data that are impossible to accurately appreciate just by looking through it. This is where charts come in. The human brain tends to be able to read and interpret images, such as bar charts or pie charts, quite easily, gaining a quick outlook on the data as a whole. In this post I will present a very facile method to embed such graphs and charts in your site using Rails 3.

The tool I’ll use to create this graphs and charts is called Highcharts. One of the advantages of Highcharts is that it’s written in pure Javascript, which makes it accessible both in development and production. We’ll talk about:

  • how to set Highcharts up
  • how to make a simple bar chart
  • how to interact with the model
  • some more options this environment provides for chart configuration

1. Setting up

First of all, you need to go to Download section on the site and choose Highcharts. All you’ll need from the downloaded folder is the highcharts.js file in the /js/ folder. You have to extract this file to your app/assets/javascripts/lib folder in your project.

Afterwards, in your application file located in your view you have to include the aforementioned file:


= javascript_include_tag "application", "lib/highcharts"

This is about it, as far as setting Highcharts up goes. Simple enough, isn’t it? Now let’s see how to make use of this library.

2. Making a simple bar chart

Let’s take a simple chart example in order to see Highcharts in action. Say, we have a list of time entries for a user (each time entry showing how much the user has worked on a certain day for a certain project). We’ll want to make a bar chart to show us for each day of the week the total amount of time worked by the user.

When creating a new chart, first step would be to set up a location where you want to render the chart. The best way to do this is to create a div in the specific place in the view where you want the chart. The div could look like this:


.user_chart{id: "user_time_chart"}

Later we will use the id to locate this specific div. In the next step we must create the actual chart. For this example we will use coffeescript, so the actual code will be separated from the view within a file (named like the respective controller), located in assets/javascripts. Let’s see how the coffeescript code for this specific situation would look like:


   user_pie_chart = ->
     new Highcharts.Chart({
       chart:
         renderTo: "user_time_chart",
         type: "column"
       title:
         text: "Your time logging"
       xAxis:
         categories: ["M", "T", "W", "Th", "F", "Sa", "Su"]
       yAxis:
         min: 0,
         title:
           text: "Time (h)"
       series: [
         {
           name: "Your time",
           data: [0, 0, 0, 0, 0, 0, 0]
         }
       ]
     })

Above we have the function that strictly creates the chart. This function should be made global and preferably included in a namespace. Afterwards the function should be called from the view where the div is located.

Obviously we start by creating a new Chart object that we proceed to configure. The options are pretty self explanatory. For example renderTo: is used to specify the location where the chart will appear. That’s why we use there the id of the div we made before. The series: option is used to enter the data. In this case the chart is empty because we entered an array filled with zeroes.

So far we’ve created a very basic chart that uses data entered by hand. Let’s see now how we can modify this chart for it to be able to interact with the model.

3. Interacting with the model data

Javascript, and coffeescript respectively, can’t interact with the model alone. Therefore we must use ruby to “feed” the data to the chart as a parameter in the function we saw above. The modified function looks like this:


   user_pie_chart = (data_series) ->
     new Highcharts.Chart({
       chart:
         renderTo: "user_time_chart",
         type: "column"
       title:
         text: "Your time logging"
       xAxis:
         categories: ["M", "T", "W", "Th", "F", "Sa", "Su"]
       yAxis:
         min: 0,
         title:
           text: "Time (h)"
       series: [
         {
           name: "Your time",
           data: data_series
         }
       ]
     })

Instead of writing the data by hand we use a parameter passed to the function. But how do we collect this data and put it together in the first place? The easiest way to do this is to use a helper function which we call as a parameter for the function. In this case the helper function would look like this:


def time_entries_user_chart_series(time_entries, start_date)
  time_entries_by_day = time_entries.where(date: start_date..Date.today).
                        group("date(date)").
                        select("date, sum(duration) as duration")
 (start_date..Date.today.end_of_week).map do |date|
    time_entry = time_entries_by_day.detect { |time_entry| time_entry.date == date}
    time_entry && time_entry.duration.to_f/3600 || 0
 end
end

This function takes as parameters a list of time entries for the current user and the starting date for which it makes the data collection. As it can be seen this function groups the time entries that fit the date criteria by date, keeping for each in time_entries_by_day the total time elapsed for that specific date. The reason why we do this is efficiency. This way we make far less queries to the database than we would by summing up manually all the time entries. Afterwards we iterate through the dates of the current week and select for each the right group which ones we convert into hours and then return.

The call for the user_pie_chart function looks like this:


  :javascript
    window.user_pie_chart(#{time_entries_user_chart_series(current_user.time_entries, Date.today.beginning_of_week)})

This call appears in the view and is responsible for generating this chart:

As we can see, the chart now successfully takes data from the database.

4. More options for Highcharts

Besides what we’ve seen so far, Highcharts permits high configurability. In this part of the post I will present a few useful options for your charts. A full list of features can be found here.

  • credits: false

Including this in your code removes the “Highcharts.com” text at the bottom of your chart.

  • tooltip:

The tooltip configures the box that comes up when you hover with the mouse over an entry in the chart. Using a function called formatter: you can set the format in which you want the data to appear. You use this.x and this.y to address the values specific to that data entry.

Also, you can include more than one data series in your charts. More chart examples can be found here. You can see different types of charts and study each of them is implemented. Another good tutorial on charts can be found on railscasts.

Did you like this post? Share it with your friends!