Create beautiful JavaScript charts with one line of Ruby

Love Ruby and data?
Join Instacart’s world-class engineering team

Line chart

<%= line_chart User.group_by_day(:created_at).count %>
Install Groupdate to use the group_by_day method

Pie chart

<%= pie_chart %>

Column chart

<%= column_chart Order.group_by_day_of_week(:created_at, format: "%a").count %>

Bar chart

<%= bar_chart %>

Area chart

<%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>

Scatter chart

<%= scatter_chart City.pluck(:size, :population), xtitle: "Size", ytitle: "Population" %>

Geo chart - Google Charts

<%= geo_chart %>

Timeline - Google Charts

<%= timeline [
  ["Washington", "1789-04-29", "1797-03-03"],
  ["Adams", "1797-03-03", "1801-03-03"],
  ["Jefferson", "1801-03-03", "1809-03-03"]
] %>

Multiple series

<%= line_chart { |goal|
    {name:, data: goal.feats.group_by_week(:created_at).count}
} %>


<%= line_chart %>

Say Goodbye To Timeouts

Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.

<%= line_chart completed_tasks_charts_path %>

And in your controller, pass the data as JSON.

class ChartsController < ApplicationController
  def completed_tasks
    render json: Task.group_by_day(:completed_at).count

For multiple series, add chart_json at the end.

render json:


Id, width, and height

<%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>

Min and max values

<%= line_chart data, min: 1000, max: 5000 %>

min defaults to 0 for charts with non-negative values. Use nil to let the charting library decide.


<%= line_chart data, colors: ["#b00", "#666"] %>

Stacked columns or bars

<%= column_chart data, stacked: true %>

Discrete axis

<%= line_chart data, discrete: true %>

Label (for single series)

<%= line_chart data, label: "Value" %>

Axis titles

<%= line_chart data, xtitle: "Time", ytitle: "Population" %>

Straight lines between points instead of a curve

<%= line_chart data, curve: false %>

Hide points

<%= line_chart data, points: false %>

Show or hide legend

<%= line_chart data, legend: false %>

Specify legend position

<%= line_chart data, legend: "bottom" %>

Defer chart creation until after the page loads

<%= line_chart data, defer: true %>

Donut chart

<%= pie_chart data, donut: true %>

Prefix, useful for currency - Chart.js, Highcharts

<%= line_chart data, prefix: "$" %>

Suffix, useful for percentages - Chart.js, Highcharts

<%= line_chart data, suffix: "%" %>

Set a thousands separator - Chart.js, Highcharts

<%= line_chart data, thousands: "," %>

Set a decimal separator - Chart.js, Highcharts

<%= line_chart data, decimal: "," %>

Show a message when data is empty

<%= line_chart data, messages: {empty: "No data"} %>

Refresh data from a remote source every n seconds

<%= line_chart url, refresh: 60 %>

You can pass options directly to the charting library with:

<%= line_chart data, library: {backgroundColor: "#eee"} %>

See the documentation for Chart.js, Google Charts, and Highcharts for more info.

Global Options

To set options for all of your charts, create an initializer config/initializers/chartkick.rb with:

Chartkick.options = {
  height: "400px",
  colors: ["pink", "#999"]

Customize the html

Chartkick.options[:html] = '<div id="%{id}" style="height: %{height};">Loading...</div>'

You capture the JavaScript in a content block with:

Chartkick.options[:content_for] = :charts_js

Then, in your layout:

<%= yield :charts_js %> <!-- Rails -->
<%= yield_content :charts_js %> <!-- Padrino -->

This is great for including all of your JavaScript at the bottom of the page.


Pass data as a Hash or Array

<%= pie_chart({"Football" => 10, "Basketball" => 5}) %>
<%= pie_chart [["Football", 10], ["Basketball", 5]] %>

For multiple series, use the format

<%= line_chart [
  {name: "Series A", data: series_a},
  {name: "Series B", data: series_b}
] %>

Times can be a time, a timestamp, or a string (strings are parsed)

<%= line_chart({ => 5, 1368174456 => 4, "2013-05-07 00:00:00 UTC" => 7}) %>

Download Charts

Chart.js only

Give users the ability to download charts. It all happens in the browser - no server-side code needed.

<%= line_chart data, download: true %>

Set the filename

<%= line_chart data, download: "boom" %>

Note: Safari will open the image in a new window instead of downloading.


Add this line to your application's Gemfile:

gem "chartkick"

Next, choose your charting library.

Charting Libraries

Note: In the instructions below, application.js must be included before the helper methods in your views, unless using the :content_for option.


In application.js, add:

//= require Chart.bundle
//= require chartkick

Google Charts

In application.js, add:

//= require chartkick

In your views, before application.js, add:

<%= javascript_include_tag "" %>


Download highcharts.js into vendor/assets/javascripts (or use yarn add highcharts in Rails 5.1+).

In application.js, add:

//= require highcharts
//= require chartkick

Works with Highcharts 2.1+


For Webpacker, use Yarn to install the JavaScript libraries:

yarn add chartkick
yarn add chart.js # or highcharts

Then include them in your pack.

import Chartkick from "chartkick";
window.Chartkick = Chartkick;

// for Chart.js
import Chart from "chart.js";
window.Chart = Chart;

// for Highcharts
import Highcharts from "highcharts";
window.Highcharts = Highcharts;

// for Google Charts
// just include in your views

Sinatra and Padrino

You must include chartkick.js manually. Download it here

<script src="chartkick.js"></script>


To specify a language for Google Charts, add:

Chartkick.configure({language: "de"});

after the JavaScript files and before your charts.

Multiple Libraries

If more than one charting library is loaded, choose between them with:

<%= line_chart data, adapter: "google" %> <!-- or highcharts or chartjs -->

JavaScript API

Access a chart with:

var chart = Chartkick.charts["chart-id"]

Get the underlying chart object with:


You can also use:


Update the data with:


You can also specify new options:

// or
chart.updateData(newData, newOptions)

Refresh the data from a remote source:


Redraw the chart with:


Loop over charts with:

Chartkick.eachChart( function(chart) {
  // do something

No Ruby? No Problem

Check out chartkick.js




Breaking changes


Chartkick uses iso8601.js to parse dates and times.


View the changelog

Chartkick follows Semantic Versioning


Everyone is encouraged to help improve this project. Here are a few ways you can help: