Highcharts in Rails 5

Add the following gems to Gemfile.

gem 'chartkick'
gem 'groupdate'

Run bundle. Create a charts controller:

rails g controller charts downloads_by_day

Make sure the following routes is defined in routes.rb.

get 'charts/downloads_by_day'

The downloadsbyday action is empty. In downloadsbyday.html.erb:

<%= line_chart Download.group_by_day(:created_at).count %>

The display shows the text loading but no chart is drawn. I was pointing the development database to sqlite instead of MySQL that had production data in development database. Changed the database configuration to use MySQL. Browsing to http://localhost:3000/charts/downloads_by_day gave the error:

Be sure to install time zone support - https://github.com/ankane/groupdate#for-mysql

In a terminal, run the command.

$mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot --force mysql

The output of this command is as follows.

Warning: Unable to load '/usr/share/zoneinfo/+VERSION' as time zone. Skipping it.
ERROR 1406 (22001) at line 39271: Data too long for column 'Abbreviation' at row 1
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.

You can ignore those warnings. To verify it worked, run:

$mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.6.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SELECT CONVERT_TZ(NOW(), '+00:00', 'Etc/UTC');
+----------------------------------------+
| CONVERT_TZ(NOW(), '+00:00', 'Etc/UTC') |
+----------------------------------------+
| 2017-02-05 20:44:18                    |
+----------------------------------------+
1 row in set (0.00 sec)

The time displayed means that it worked.

Troubleshooting Problems

The chart was not loading on the webpage. I copied the SQL query from the log and ran it in mysql console.

Check Data

Check the results of the query fired by ActiveRecord in mysql console.

$mysql -u user-name -p
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 5.6.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+---------------------+
| Database            |
+---------------------+
| information_schema  |
| merlot              |
| test                |
+---------------------+
13 rows in set (0.00 sec)

mysql> use merlot;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql>  SELECT COUNT(*) AS count_all, DATE_ADD(CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(created_at, INTERVAL 0 second), '+00:00', 'Etc/UTC'), '%Y-%m-%d 00:00:00'), 'Etc/UTC', '+00:00'), INTERVAL 0 second) AS day FROM `downloads` WHERE (created_at IS NOT NULL) GROUP BY DATE_ADD(CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(created_at, INTERVAL 0 second), '+00:00', 'Etc/UTC'), '%Y-%m-%d 00:00:00'), 'Etc/UTC', '+00:00'), INTERVAL 0 second);
+-----------+---------------------+
| count_all | day                 |
+-----------+---------------------+
|         1 | 2016-12-08 00:00:00 |
|         2 | 2016-12-09 00:00:00 |
|        51 | 2016-12-11 00:00:00 |
|         9 | 2016-12-12 00:00:00 |
|         2 | 2016-12-13 00:00:00 |
|        15 | 2016-12-14 00:00:00 |
|        24 | 2016-12-15 00:00:00 |
|         8 | 2016-12-16 00:00:00 |
|        57 | 2016-12-17 00:00:00 |
|        55 | 2016-12-18 00:00:00 |
|        37 | 2016-12-19 00:00:00 |
|        57 | 2016-12-20 00:00:00 |
|         7 | 2016-12-21 00:00:00 |
|         5 | 2016-12-22 00:00:00 |
|        21 | 2016-12-23 00:00:00 |
|         2 | 2016-12-24 00:00:00 |
|        28 | 2016-12-25 00:00:00 |
|         6 | 2016-12-26 00:00:00 |
|        19 | 2016-12-27 00:00:00 |
|        59 | 2016-12-29 00:00:00 |
|        50 | 2016-12-30 00:00:00 |
|        14 | 2016-12-31 00:00:00 |
|        10 | 2017-01-01 00:00:00 |
|        22 | 2017-01-02 00:00:00 |
|        32 | 2017-01-03 00:00:00 |
|         5 | 2017-01-04 00:00:00 |
|         9 | 2017-01-05 00:00:00 |
|         2 | 2017-01-06 00:00:00 |
|       322 | 2017-01-07 00:00:00 |
|       162 | 2017-01-08 00:00:00 |
|       133 | 2017-01-09 00:00:00 |
|       147 | 2017-01-10 00:00:00 |
|        61 | 2017-01-11 00:00:00 |
|        79 | 2017-01-12 00:00:00 |
|        19 | 2017-01-13 00:00:00 |
|        33 | 2017-01-14 00:00:00 |
|        71 | 2017-01-15 00:00:00 |
|        37 | 2017-01-16 00:00:00 |
|        22 | 2017-01-17 00:00:00 |
|        30 | 2017-01-18 00:00:00 |
|        12 | 2017-01-19 00:00:00 |
|        81 | 2017-01-20 00:00:00 |
|       100 | 2017-01-21 00:00:00 |
|        12 | 2017-01-22 00:00:00 |
|        67 | 2017-01-23 00:00:00 |
|        17 | 2017-01-24 00:00:00 |
|        64 | 2017-01-25 00:00:00 |
|         8 | 2017-01-26 00:00:00 |
|       136 | 2017-01-27 00:00:00 |
|        42 | 2017-01-28 00:00:00 |
|        29 | 2017-01-29 00:00:00 |
|        83 | 2017-01-30 00:00:00 |
|        79 | 2017-01-31 00:00:00 |
|        24 | 2017-02-01 00:00:00 |
|         8 | 2017-02-02 00:00:00 |
|        23 | 2017-02-03 00:00:00 |
|        27 | 2017-02-04 00:00:00 |
|        76 | 2017-02-05 00:00:00 |
+-----------+---------------------+
58 rows in set (0.01 sec)

You can see that we are connected to the right database and have data.

View Page Source in the Browser

Viewing the page source in the browser shows that the data is being used by line chart:

<div id="chart-1" style="height: 300px; width: 100%; text-align: center; color: #999; line-height: 300px; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">Loading...</div><script type="text/javascript">
  new Chartkick.LineChart("chart-1", {"2016-12-08":1,"2016-12-09":2,"2016-12-10":0,"2016-12-11":51,"2016-12-12":9,"2016-12-13":2,"2016-12-14":15,"2016-12-15":24,"2016-12-16":8,"2016-12-17":57,"2016-12-18":55,"2016-12-19":37,"2016-12-20":57,"2016-12-21":7,"2016-12-22":5,"2016-12-23":21,"2016-12-24":2,"2016-12-25":28,"2016-12-26":6,"2016-12-27":19,"2016-12-28":0,"2016-12-29":59,"2016-12-30":50,"2016-12-31":14,"2017-01-01":10,"2017-01-02":22,"2017-01-03":32,"2017-01-04":5,"2017-01-05":9,"2017-01-06":2,"2017-01-07":322,"2017-01-08":162,"2017-01-09":133,"2017-01-10":147,"2017-01-11":61,"2017-01-12":79,"2017-01-13":19,"2017-01-14":33,"2017-01-15":71,"2017-01-16":37,"2017-01-17":22,"2017-01-18":30,"2017-01-19":12,"2017-01-20":81,"2017-01-21":100,"2017-01-22":12,"2017-01-23":67,"2017-01-24":17,"2017-01-25":64,"2017-01-26":8,"2017-01-27":136,"2017-01-28":42,"2017-01-29":29,"2017-01-30":83,"2017-01-31":79,"2017-02-01":24,"2017-02-02":8,"2017-02-03":23,"2017-02-04":27,"2017-02-05":76}, {});
</script>

The chart is still not loading. I checked the readme of the Highcharts homepage, it is compatible with jQuery version 3.1.1. I took a step back and focused on the basics by playing with the hello world for Highcharts, you can read about Highcharts Basics and play with a simple bar chart. This program helped me to answer questions such as where should the javascript references go? What version of jQuery works with Highcharts and so on. Reducing the number of unknowns helps to get a simple program working. We can gradually improve it, for instance replace hard-coded data in the Javascript with JSON data from the server.

Rendering the Chart

I was getting the error: Chartkick is not defined. I added:

//= require chartkick

in application.js.

I added

<%= javascript_include_tag "chartkick" %>

in the application layout file. I got the error: Error Loading Chart: No adapter found. So I added the Google charts:

<%= javascript_include_tag "http://www.google.com/jsapi", "chartkick" %>

It finally worked! To use Highcharts, switch the adapter in the layout file:

<%= javascript_include_tag "http://code.highcharts.com/highcharts.js", "chartkick" %>

The graph now looks prettier than Google charts. But, the dates displayed are not as many as the Google charts. To display all the dates on the x-axis, Highcharts requires tick interval to be specified. This can be customized in chartkick as follows:

<%= line_chart Download.group_by_day(:created_at).count, {discrete: true} %>

Twitter Bootstrap 4

Note: The chartkick documentation says: Download highcharts.js into vendor/assets/javascripts. In application.js, add:

//= require highcharts
//= require chartkick

Then, in your layout:

<%= yield :charts_js %>

This is great for including all of your JavaScript at the bottom of the page. This is the right way to do it in production. I got it working the quick and dirty way to get a feel for the Chartkick and Highcharts libraries. We can also send JSON in downloads_by_day action and use that JSON data in the view. This is the ideal way to implement the charting functionality. You can download the source code ckick to play with the charts in Rails 5, chartkick 2.2.2, groupdate 3.2.0 and active_median 0.1.4. This example Rails 5 project follows the steps of the tutorial in the references section below.

References


Related Articles


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.