Rails Charts with Chartkick

I’d like to create a minimal Rails project that can display a chart. The first tutorial I’ve got to work for me is called Charts with Chartkick and Groupdate. I’m going to pick it apart and turn it into a bare-bones how-to.

I’ve turned this post upside-down. The most polished procedure is at the top and the earlier versions get less and less successful on the way down.

Final Procedure

This procedure goes from zero to “Rails app with a chart”. I’ll show anything that happens at a bash prompt in fixed-width font with bold showing the commands entered. When the responses are too long I’ll abbreviate them using ellipses (…).

I’ll assume you have Ruby on Rails installed (if not, go here!). I’m using a Mac with macOS 10.13.2 with these versions installed:

~: ruby -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]
~: rails -v
Rails 5.1.4

Basic Rails Project

Let’s create a basic Rails app that we can add charting on to.

  1. Create a Rails project. I’ll call mine Chart1
    ~: rails new Chart1
     create 
     create README.md
     create Rakefile
     create config.ru
     create .gitignore
     create Gemfile
     run git init from "."
    Initialized empty Git repository in /Users/prawnhead/Chart1/.git/
     create app
    ...
    ~:
  2. Switch to the project folder
    ~: cd Chart1/
    ~/Chart1: 
    
  3. Create the databases
    ~/Chart1: rake db:create
    Created database 'db/development.sqlite3'
    Created database 'db/test.sqlite3'
    ~/Chart1: 
    
  4. Create a model. We’ll use an integer field to have something numerical to chart later.
    ~/Chart1: rails generate model User count:integer
    Running via Spring preloader in process 28012
     invoke active_record
     create db/migrate/20180119054940_create_users.rb
     create app/models/user.rb
     invoke test_unit
     create test/models/user_test.rb
     create test/fixtures/users.yml
    ~/Chart1: 
    
  5. Migrate the model into the database
    ~/Chart1: rake db:migrate
    == 20180119054940 CreateUsers: migrating ======================================
    -- create_table(:users)
     -> 0.0008s
    == 20180119054940 CreateUsers: migrated (0.0009s) =============================
    
    ~/Chart1:
  6. Add ‘hirb’ to the Gemfile. This just makes data printed into the Rails Console appear as a table, which is much easier to understand than the default format. Open Gemfile in the root folder of the application and make hirb the first gem. Below are the top 15 lines of my Gemfile
    source 'https://rubygems.org'
    
    git_source(:github) do |repo_name|
     repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
     "https://github.com/#{repo_name}.git"
    end
    
    gem 'hirb'
    
    # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
    gem 'rails', '~> 5.1.4'
    # Use sqlite3 as the database for Active Record
    gem 'sqlite3'
    # Use Puma as the app server
    gem 'puma', '~> 3.7'
  7. Start the Rails console:
    ~/Chart1: rails c
    Running via Spring preloader in process 28065
    Loading development environment (Rails 5.1.4)
    Cannot read termcap database;
    using dumb terminal settings.
    irb(main):001:0>
  8. Add some data. I’m deliberately making the created_at timestamps on different days.
irb(main):001:0> User.all
D, [2018-01-19T16:50:10.394442 #28065] DEBUG -- : User Load (0.9ms) SELECT "users".* FROM "users"
=> #<ActiveRecord::Relation []>
irb(main):002:0> User.create(count: 400, created_at: 3.days.ago)
D, [2018-01-19T16:50:37.075832 #28065] DEBUG -- : (0.0ms) begin transaction
D, [2018-01-19T16:50:37.077938 #28065] DEBUG -- : SQL (0.4ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 400], ["created_at", "2018-01-16 05:50:37.069147"], ["updated_at", "2018-01-19 05:50:37.076248"]]
D, [2018-01-19T16:50:37.080716 #28065] DEBUG -- : (2.3ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  1 |   400 | 2018-01-16 05:50:37 UTC | 2018-01-19 05:50:37 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):003:0> User.create(count: 200, created_at: 2.days.ago)
D, [2018-01-19T16:50:47.606314 #28065] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-19T16:50:47.608132 #28065] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 200], ["created_at", "2018-01-17 05:50:47.604584"], ["updated_at", "2018-01-19 05:50:47.606744"]]
D, [2018-01-19T16:50:47.611080 #28065] DEBUG -- : (2.4ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  2 |   200 | 2018-01-17 05:50:47 UTC | 2018-01-19 05:50:47 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):004:0> User.create(count: 300, created_at: 1.days.ago)
D, [2018-01-19T16:50:56.861733 #28065] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-19T16:50:56.863685 #28065] DEBUG -- : SQL (0.6ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 300], ["created_at", "2018-01-18 05:50:56.860100"], ["updated_at", "2018-01-19 05:50:56.862141"]]
D, [2018-01-19T16:50:56.866370 #28065] DEBUG -- : (2.2ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  3 |   300 | 2018-01-18 05:50:56 UTC | 2018-01-19 05:50:56 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):005:0> User.create(count: 100) 
D, [2018-01-19T16:51:04.060152 #28065] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-19T16:51:04.062460 #28065] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 100], ["created_at", "2018-01-19 05:51:04.060719"], ["updated_at", "2018-01-19 05:51:04.060719"]]
D, [2018-01-19T16:51:04.065403 #28065] DEBUG -- : (2.4ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  4 |   100 | 2018-01-19 05:51:04 UTC | 2018-01-19 05:51:04 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):006:0> User.all 
D, [2018-01-19T16:51:09.100250 #28065] DEBUG -- : User Load (0.3ms) SELECT "users".* FROM "users"
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  1 |   400 | 2018-01-16 05:50:37 UTC | 2018-01-19 05:50:37 UTC |
|  2 |   200 | 2018-01-17 05:50:47 UTC | 2018-01-19 05:50:47 UTC |
|  3 |   300 | 2018-01-18 05:50:56 UTC | 2018-01-19 05:50:56 UTC |
|  4 |   100 | 2018-01-19 05:51:04 UTC | 2018-01-19 05:51:04 UTC |
+----+-------+-------------------------+-------------------------+
4 rows in set
irb(main):007:0> exit
~/Chart1:

OK, so now we have a basic Rails app with one model “User” that only has one custom field “count” and we’ve added 4 objects to that collection. This is a terribly basic data set that we can chart later.

Building a View

We need a view on which to display the chart and there’s a bit of plumbing we need behind that too.

  1. Create a users controller
    1. Create the file app/controllers/users_controller.rb
    2. Populate the file with the following:
      class UsersController < ApplicationController
        def index
          @users = User.all
      
          respond_to do |format|
            format.html
          end
        end
      end
  2. Create a charts controller.
    1. Add the file app/controllers/charts_controller.rb
    2. Populate the controller with the following:
      class ChartsController < ApplicationController
        def new_users
          render json: User.group_by_day(:created_at).sum(:count)
        end
      end
  3. Create a users view
    1. Create the folder app/views/users
    2. Create the file app/views/users/index.html.erb
    3. Populate the new file with some very basic HTML. We’ll come back later and add HTML and Javascript to generate the chart:
      <h1>Users</h1>
  4. Set up a route to the users view. At the same time we’ll set up a namespace for charts so we can pull a JSON data set from http://localhost:3000/charts/new-users
    1. Edit the file config/routes.rb
    2. Replace the file contents with the following:
      Rails.application.routes.draw do
        resources :users
      
        namespace :charts do
          get "new-users"
        end
      end

Now we should be able to test that the view works. Start rails server and access http://localhost:3000/users in a browser.

Users Page
Users Page

It’s not a lot, but it works. Now let’s add the chart!

Creating a Chart

  1. We created the data source for the chart above, but it doesn ‘t work yet http://localhost:3000/charts/new-users. It needs the groupdate gem and, while we’re at that we might as well add chartkick too.
    Charts New-Users data source fails
    Charts New-Users data source fails
    1. Edit Gemfile in the root folder of the app. Append to the bottom of the file these two gems:
      gem 'chartkick'
      gem 'groupdate'
      
    2. Restart rails server
    3. Check http://localhost:3000/charts/new-users again, this time it should provide a JSON-formatted data set.

      Charts New-Users data set
      Charts New-Users data set
  2. With a working data set we can create the chart.
    1. Edit app/views/users/index.html.erb again. Replace the contents with this:
      <h1>Users</h1>
      <%= line_chart charts_new_users_path %>
    2. Now try the users page again http://localhost:3000/users
      Users Chart not loading
      Users Chart not loading

      Well. Almost.

    3. We only need a minor amendment to the Javascript on the page to make it all work. Edit app/assets/javascripts/application.js and make the//= require lines at the bottom of the file look like this:
      //= require rails-ujs
      //= require turbolinks
      //= require Chart.bundle
      //= require chartkick
      //= require_tree
    4. Try that web page again. http://localhost:3000/users

      Users Chart successful
      Users Chart successful

So that should be it. You’ve not only seen all the steps required to get a Chartkick chart to work, but also saw at which step the various configurations are required.

The remainder of this post is just reference material for me if I need to come back to this later.

Run, Done and Won

Let’s see if it works:

  1. Follow the link to Source code from this episode below the video.
  2. Downloaded the source code using the Clone or download button
  3. Unzip the file, creating the gorails-episode-194-master folder
  4. Check the routes.rb file for resources and have a look in ./app/views/ for views: there’s one called users
  5. Open a terminal and changed to the ~/Downloads/gorails-episode-194-master folder
  6. Run rails s
  7. Open http://localhost:3000/users and …
  8. It fails with “Migrations are pending”
  9. In terminal, Ctrl-C to close rails server
  10.  Try to run rake db:create and get:
    Gem::LoadError: You have already activated rake 12.3.0, but your Gemfile requires rake 12.0.0. Prepending `bundle exec` to your command may solve this.
  11. OK, then following this advice: bundle exec rake db:setup
    Database 'db/development.sqlite3' already exists
    Created database 'db/test.sqlite3'
    -- create_table("users", {:force=>:cascade})
    -> 0.0028s
    -- create_table("users", {:force=>:cascade})
    -> 0.0020s
    ~/Downloads/gorails-episode-194-master:
  12. Now run rails s
  13. Open http://localhost:3000/users and …
  14. Get a nice pair of graphs.
Charts with Chartkick and Groupdate
Charts with Chartkick and Groupdate

I should also show what versions of Ruby and Rails I’m running:

~/Downloads/gorails-episode-194-master: ruby -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]
~/Downloads/gorails-episode-194-master: rails -v
Rails 5.1.1

Picking it Apart

I’ll try to pick it apart with my limited Ruby and Rails understanding. First, the HTML. The entire BODY section looks like this:

<body>
<h1>Users</h1>

<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", "/charts/new-users", {});
</script>

<h4>By Month</h4>
<div id="chart-2" 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.ColumnChart("chart-2", "/charts/by-month-users", {});
</script>

</body>

We can see the DIV tags create objects chart-1 and chart-2 in the DOM and the SCRIPT tags immediately following each modify those objects to insert the chart and asynchronously source the data from /charts/new-users and /charts/by-month-users. The view that creates the HTML is gorails-episode-194-master/app/views/users/index.html.erb, that looks like this:

<h1>Users</h1>
<%= line_chart charts_new_users_path %>
<h4>By Month</h4>
<%= column_chart charts_by_month_users_path %>

I expect in the first script line that line_chart is a call to Chartkick and charts_new_users_path defines the data source. I searched the app for “charts_new_users_path” but could only find it in this ERB file. The URL for the data sources (eg. /charts/new-users) defined in the HTML suggests there is a model called chart and that defines a method called new-users. Is there a charts model that defines a new_users method? Yes! OK, the gorails-episode-194-master/app/controllers/charts_controller.rb file defines the new_users  and also by_month_users methods. So there’s the data sources worked out.

Hacking Around

Can I get one of these graphs to render a data source from my production Rails server? The data source is currently delivered from the URL http://localhost:3000/charts/new-users as JSON (suits me!) and looks like this:

2014-01-01 791
2014-02-01 1273
2014-03-01 1647
2014-04-01 1592
2014-05-01 1451
2014-06-01 1585
2014-07-01 1396
2014-08-01 1630
2014-09-01 1415

I should be able to quickly hack together a Rails app that delivers a similar data source:

~/Junk: rails new Source
...
~/Junk: cd Source
~/Junk/Source: rake db:create
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
~/Junk/Source: rails generate scaffold User count:integer
...
~/Junk/Source: rake db:migrate
== 20180118031547 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0008s
== 20180118031547 CreateUsers: migrated (0.0009s) =============================

I made a quick edit on the Gemfile to add gem 'hirb' for some nice formatting in the Rails console. Then I added a few rows of data.

~/Junk/Source: rails c
Running via Spring preloader in process 22643
Loading development environment (Rails 5.1.4)
Cannot read termcap database;
using dumb terminal settings.
irb(main):001:0> User.all
 User Load (0.9ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):002:0> User.create(count: 100)
D, [2018-01-18T14:16:43.607357 #22672] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-18T14:16:43.609649 #22672] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 100], ["created_at", "2018-01-18 03:16:43.607862"], ["updated_at", "2018-01-18 03:16:43.607862"]]
D, [2018-01-18T14:16:43.612328 #22672] DEBUG -- : (2.2ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  1 |   100 | 2018-01-18 03:16:43 UTC | 2018-01-18 03:16:43 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):003:0> User.create(count: 12, created_at: 1.days.ago)
D, [2018-01-18T14:17:12.820234 #22672] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-18T14:17:12.822068 #22672] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 12], ["created_at", "2018-01-17 03:17:12.818513"], ["updated_at", "2018-01-18 03:17:12.820616"]]
D, [2018-01-18T14:17:12.824778 #22672] DEBUG -- : (2.2ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  2 |    12 | 2018-01-17 03:17:12 UTC | 2018-01-18 03:17:12 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):004:0> User.create(count: 75, created_at: 2.days.ago)
D, [2018-01-18T14:17:25.982540 #22672] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-18T14:17:25.984384 #22672] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 75], ["created_at", "2018-01-16 03:17:25.980931"], ["updated_at", "2018-01-18 03:17:25.982955"]]
D, [2018-01-18T14:17:25.987234 #22672] DEBUG -- : (2.4ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              |              updated_at |
+----+-------+-------------------------+-------------------------+
|  3 |    75 | 2018-01-16 03:17:25 UTC | 2018-01-18 03:17:25 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):005:0> User.create(count: 201, created_at: 3.days.ago)
D, [2018-01-18T14:17:34.926544 #22672] DEBUG -- : (0.1ms) begin transaction
D, [2018-01-18T14:17:34.928404 #22672] DEBUG -- : SQL (0.5ms) INSERT INTO "users" ("count", "created_at", "updated_at") VALUES (?, ?, ?) [["count", 201], ["created_at", "2018-01-15 03:17:34.924931"], ["updated_at", "2018-01-18 03:17:34.926955"]]
D, [2018-01-18T14:17:34.931340 #22672] DEBUG -- : (2.4ms) commit transaction
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  4 |   201 | 2018-01-15 03:17:34 UTC | 2018-01-18 03:17:34 UTC |
+----+-------+-------------------------+-------------------------+
1 row in set
irb(main):006:0> User.all 
D, [2018-01-18T14:17:38.322616 #22672] DEBUG -- : User Load (0.2ms) SELECT "users".* FROM "users"
+----+-------+-------------------------+-------------------------+
| id | count | created_at              | updated_at              |
+----+-------+-------------------------+-------------------------+
|  1 |   100 | 2018-01-18 03:16:43 UTC | 2018-01-18 03:16:43 UTC |
|  2 |    12 | 2018-01-17 03:17:12 UTC | 2018-01-18 03:17:12 UTC |
|  3 |    75 | 2018-01-16 03:17:25 UTC | 2018-01-18 03:17:25 UTC |
|  4 |   201 | 2018-01-15 03:17:34 UTC | 2018-01-18 03:17:34 UTC |
+----+-------+-------------------------+-------------------------+
4 rows in set
irb(main):007:0> exit
~/Junk/Source:

Since I’ve got the graphing example running on port 3000, I need to run my data source on a separate port number:

~/Junk/Source: rails s -p 3001
=> Booting Puma
=> Rails 5.1.4 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.11.0 (ruby 2.4.0-p0), codename: Love Song
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3001
Use Ctrl-C to stop

My dummy data is now accessible at http://localhost:3001/users.json

~: curl http://localhost:3001/users.json | python -m json.tool
 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
100 575 0 575 0 0 30330 0 --:--:-- --:--:-- --:--:-- 31944
[
 {
 "count": 100,
 "created_at": "2018-01-18T03:16:43.607Z",
 "id": 1,
 "updated_at": "2018-01-18T03:16:43.607Z",
 "url": "http://localhost:3001/users/1.json"
 },
 {
 "count": 12,
 "created_at": "2018-01-17T03:17:12.818Z",
 "id": 2,
 "updated_at": "2018-01-18T03:17:12.820Z",
 "url": "http://localhost:3001/users/2.json"
 },
 {
 "count": 75,
 "created_at": "2018-01-16T03:17:25.980Z",
 "id": 3,
 "updated_at": "2018-01-18T03:17:25.982Z",
 "url": "http://localhost:3001/users/3.json"
 },
 {
 "count": 201,
 "created_at": "2018-01-15T03:17:34.924Z",
 "id": 4,
 "updated_at": "2018-01-18T03:17:34.926Z",
 "url": "http://localhost:3001/users/4.json"
 }
]
~:

Now I need the quick-and-dirty version of this JSON, just date and count columns with no attributes. So how does the example do it? Ah, it’s gorails-episode-194-master/app/controllers/charts_controller.rb. I’ll just whack that file into my dummy project “Source”. When I try to access it though, there’s no route to this resource

~: curl http://localhost:3001/charts/new_users | python -m json.tool
 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
100 52768 100 52768 0 0 120k 0 --:--:-- --:--:-- --:--:-- 120k
No JSON object could be decoded
~:

Again borrowing from the example project, I just need to create a namespace in the episode-194-master/app/config/routes.rb file.

Rails.application.routes.draw do
 resources :users
 # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

# Begin added
 namespace :charts do
 get "new-users"
 # get "by-month-users"
 end
 # End Added
end

Going back to the curl command failed just the same. I wonder if I need to restart the Rails server? Nope. Oh hey, if I try to hit the URL in a browser it comes back with undefined method ‘group_by_month’ for #<Class:0x007febc43cc1b8>. Cool, I guess I just need a gem for that sucker. Back to the video transcript I need the gem called ‘groupdate’.

  1. Add the line gem 'groupdate' to Gemfile.
  2. In the bash window running the rails server, hit Ctrl-C to stop the server
  3. Do a bundle install
  4. Restart the rails server using rails s -p 3001

And now in the browser I have a single data pair because my five data points are all in the same month. I should use group_by_day, which I just assume to exist. But when I go back to a bash prompt to access the same data it doesn’t work. After some playing around I realised my mistake. I’ve used a hyphen in the browser (http://localhost:3001/charts/new-users) and an underscore in the bash window (http://localhost:3001/charts/new_users). face_palm. Or should that be face-palm?

After a bit of mucking around trying to find the correct syntax to extract the JSON I need, I came up with this version of the charts_controller.rb file:

class ChartsController < ApplicationController

  def new_users
    render json: User.group_by_day(:created_at).sum(:count)
  end
end

So I should have a data source that does not belong to the charting example I downloaded, but that is interchangeable with it. Now I just need to configure the charting page with the new data source! I modified the index.html.erb file thusly:

<h1>External JSON</h1>
<%= line_chart "http://localhost:3001/charts/new-users/" %>

<h1>Users</h1>
<%= line_chart charts_new_users_path %>

<h1>By Month</h1>
<%= column_chart charts_by_month_users_path %>

And after that I got stuck in a vortex. No matter what I tried, the new chart would not render. The server providing the data (on port 3001) acknowledged the request, but saw it as an OPTION (not GET?) request.

Started OPTIONS "/charts/new-users/" for 127.0.0.1 at 2018-01-18 18:56:02 +1100
 (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
 
ActionController::RoutingError (No route matches [OPTIONS] "/charts/new-users"):

No matter what I did with underscores and hyphens, routes, Ruby code, nothing worked. This link says plainly that “Rails can’t handle OPTIONS requests” and, while I still don’t understand why I’m making an OPTIONS request at all, I’ve decided the fastest path to success is to put the charting logic into the server with the data I want charted.

First Implementation

With all that I’ve learned above, I need to get my first scratch-built Rails project to display a chart. The process from here goes (I think!):

  1. Add gems for Chartkick and Groupdate
  2. Bundle install the new gems
  3. Modify views/users/index.html.erb to create a chart
  4. Run the server and see what fails!
  5. Chart is not populated. I can see from the Rails console that there’s never a request for data from the server.
  6. After trying many things to fix it, I finally found app/assets/javascripts/application.js didn’t have ‘require’ directives for Chart.bundle and chartkick. I modified the file.
  7. Restarted the rails server.
  8. Boom! The chart loaded.