# Technical Documentation: ankane/chartkick
> ℹ️ **Provenance:** Hybrid Fusion: `ankane/chartkick` (README + 3 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/ankane/chartkick) · Recency: Active (< 180 days)
## 1. Project Overview & Quickstart (ankane/chartkick)
# Chartkick
Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries!
[See it in action](https://chartkick.com)
:fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega)
:two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median)
[](https://github.com/ankane/chartkick/actions)
## Quick Start
Add this line to your application’s Gemfile:
```ruby
gem "chartkick"
```
Then follow the instructions for your JavaScript setup:
- [Importmap](#importmap) (Rails default)
- [Bun, esbuild, rollup.js, or Webpack](#bun-esbuild-rollupjs-or-webpack)
- [Sprockets](#sprockets)
This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries and frameworks, see [these instructions](#additional-charting-libraries).
### Importmap
In `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
pin "Chart.bundle", to: "Chart.bundle.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
import "Chart.bundle"
```
### Bun, esbuild, rollup.js, or Webpack
Run:
```sh
bun add chartkick chart.js
# or
yarn add chartkick chart.js
```
And in `app/javascript/application.js`, add:
```js
import "chartkick/chart.js"
```
### Sprockets
In `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
//= require Chart.bundle
```
## Charts
Line chart
```erb
<%= line_chart User.group_by_day(:created_at).count %>
```
Pie chart
```erb
<%= pie_chart Goal.group(:name).count %>
```
Column chart
```erb
<%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>
```
Bar chart
```erb
<%= bar_chart Shirt.group(:size).sum(:price) %>
```
Area chart
```erb
<%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
```
Scatter chart
```erb
<%= scatter_chart City.pluck(:size, :population) %>
```
Geo chart - *Google Charts*
```erb
<%= geo_chart Medal.group(:country).count %>
```
Timeline - *Google Charts*
```erb
<%= timeline [
["Washington", "1789-04-29", "1797-03-03"],
["Adams", "1797-03-03", "1801-03-03"],
["Jefferson", "1801-03-03", "1809-03-03"]
] %>
```
Multiple series
```erb
<%= line_chart [
{name: "Workout", data: {"2026-01-01" => 3, "2026-01-02" => 4}},
{name: "Call parents", data: {"2026-01-01" => 5, "2026-01-02" => 3}}
] %>
```
or
```erb
<%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %>
```
## Data
Data can be a hash, array, or URL.
#### Hash
```erb
<%= line_chart({"2026-01-01" => 2, "2026-01-02" => 3}) %>
```
#### Array
```erb
<%= line_chart [["2026-01-01", 2], ["2026-01-02", 3]] %>
```
#### URL
Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
```erb
<%= line_chart completed_tasks_charts_path %>
```
And in your controller, pass the data as JSON.
```ruby
class ChartsController < ApplicationController
def completed_tasks
render json: Task.group_by_day(:completed_at).count
end
end
```
For multiple series, add `chart_json` at the end.
```ruby
render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json
```
## Options
Id, width, and height
```erb
<%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>
```
Min and max values
```erb
<%= 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.
Min and max for x-axis - *Chart.js*
```erb
<%= line_chart data, xmin: "2026-01-01", xmax: "2026-02-01" %>
```
Colors
```erb
<%= line_chart data, colors: ["#b00", "#666"] %>
```
Stacked columns or bars
```erb
<%= column_chart data, stacked: true %>
```
Discrete axis
```erb
<%= line_chart data, discrete: true %>
```
Label (for single series)
```erb
<%= line_chart data, label: "Value" %>
```
Axis titles
```erb
<%= line_chart data, xtitle: "Time", ytitle: "Population" %>
```
Straight lines between points instead of a curve
```erb
<%= line_chart data, curve: false %>
```
Hide points
```erb
<%= line_chart data, points: false %>
```
Show or hide legend
```erb
<%= line_chart data, legend: false %>
```
Specify legend position
```erb
<%= line_chart data, legend: "bottom" %>
```
Donut chart
```erb
<%= pie_chart data, donut: true %>
```
Prefix, useful for currency - *Chart.js, Highcharts*
```erb
<%= line_chart data, prefix: "$" %>
```
Suffix, useful for percentages - *Chart.js, Highcharts*
```erb
<%= line_chart data, suffix: "%" %>
```
Set a thousands separator - *Chart.js, Highcharts*
```erb
<%= line_chart data, thousands: "," %>
```
Set a decimal separator - *Chart.js, Highcharts*
```erb
<%= line_chart data, decimal: "," %>
```
Set significant digits - *Chart.js, Highcharts*
```erb
<%= line_chart data, precision: 3 %>
```
Set rounding - *Chart.js, Highcharts*
```erb
<%= line_chart data, round: 2 %>
```
Show insignificant zeros, useful for currency - *Chart.js, Highcharts*
```erb
<%= line_chart data, round: 2, zeros: true %>
```
Friendly byte sizes - *Chart.js*
```erb
<%= line_chart data, bytes: true %>
```
Specify the message when data is loading
```erb
<%= line_chart data, loading: "Loading..." %>
```
Specify the message when data is empty
```erb
<%= line_chart data, empty: "No data" %>
```
Refresh data from a remote source every `n` seconds
```erb
<%= line_chart url, refresh: 60 %>
```
You can pass options directly to the charting library with:
```erb
<%= line_chart data, library: {backgroundColor: "#eee"} %>
```
See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info. For Chart.js plugins, check out [this guide](guides/Chartjs-Plugins.md).
To customize datasets in Chart.js, use:
```erb
<%= line_chart data, dataset: {borderWidth: 10} %>
```
You can pass this option to individual series as well.
### Global Options
To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with:
```ruby
Chartkick.options = {
height: "400px",
colors: ["#b00", "#666"]
}
```
Customize the html
```ruby
Chartkick.options[:html] = '%{loading}'
```
You capture the JavaScript in a content block with:
```ruby
Chartkick.options[:content_for] = :charts_js
```
Then, in your layout, use:
```erb
<%= yield :charts_js %>
```
For Padrino, use `yield_content` instead of `yield`.
This is great for including all of your JavaScript at the bottom of the page.
### Multiple Series
You can pass a few options with a series:
- `name`
- `data`
- `color`
- `dataset` - *Chart.js only*
- `points` - *Chart.js only*
- `curve` - *Chart.js only*
### Code
If you want to use the charting library directly, get the code with:
```erb
<%= line_chart data, code: true %>
```
The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical.
### Download Charts
*Chart.js only*
Give users the ability to download charts. It all happens in the browser - no server-side code needed.
```erb
<%= line_chart data, download: true %>
```
Safari will open the image in a new window instead of downloading.
Set the filename
```erb
<%= line_chart data, download: {filename: "boom"} %>
```
Set the background color
```erb
<%= line_chart data, download: {background: "#ffffff"} %>
```
Set title
```erb
<%= line_chart data, title: "Awesome chart" %>
```
## Additional Charting Libraries
- [Google Charts](#google-charts)
- [Highcharts](#highcharts)
### Google Charts
In your layout or views, add:
```erb
<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
```
For Importmap (Rails default), in `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
```
For Bun, esbuild, rollup.js, or Webpack, run:
```sh
bun add chartkick
# or
yarn add chartkick
```
And in `app/javascript/packs/application.js`, add:
```js
import "chartkick"
```
For Sprockets, in `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
```
To specify a language or Google Maps API key, use:
```js
Chartkick.configure({language: "de", mapsApiKey: "..."})
```
before your charts.
### Highcharts
For Importmap (Rails default), run:
```sh
bin/importmap pin highcharts --download
```
And in `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
import Highcharts from "highcharts"
window.Highcharts = Highcharts
```
For Bun, esbuild, rollup.js, or Webpack, run:
```sh
bun add chartkick highcharts
# or
yarn add chartkick highcharts
```
And in `app/javascript/packs/application.js`, add:
```js
import "chartkick/highcharts"
```
For Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts`), and in `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
//= require highcharts
```
### Multiple Libraries
If more than one charting library is loaded, choose between them with:
```erb
<%= line_chart data, adapter: "google" %>
```
## Sinatra and Padrino
Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js) and include it manually.
```html
```
Then include the charting library.
Chart.js - download [Chart.js](https://unpkg.com/chart.js@4/dist/chart.umd.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.js)
```html
```
Google Charts
```html
```
Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js)
```html
```
## JavaScript API
Access a chart with:
```javascript
var chart = Chartkick.charts["chart-id"]
```
Get the underlying chart object with:
```javascript
chart.getChartObject()
```
You can also use:
```javascript
chart.getElement()
chart.getData()
chart.getOptions()
chart.getAdapter()
```
Update the data with:
```javascript
chart.updateData(newData)
```
You can also specify new options:
```javascript
chart.setOptions(newOptions)
// or
chart.updateData(newData, newOptions)
```
Refresh the data from a remote source:
```javascript
chart.refreshData()
```
Redraw the chart with:
```javascript
chart.redraw()
```
Destroy the chart with:
```javascript
chart.destroy()
```
Loop over charts with:
```javascript
Chartkick.eachChart(function (chart) {
// do something
})
```
## Content Security Policy (CSP)
Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md)
## Tutorials
- [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate)
- [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M)
- [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/)
- [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/)
## History
View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md)
## Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- [Report bugs](https://github.com/ankane/chartkick/issues)
- Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
```sh
git clone https://github.com/ankane/chartkick.git
cd chartkick
bundle install
bundle exec rake test
```
## 2. In-Tree Documentation Chapters (ankane/chartkick)
## File: README.md
# Chartkick
Create beautiful JavaScript charts with one line of Ruby. No more fighting with charting libraries!
[See it in action](https://chartkick.com)
:fire: For admin charts and dashboards, check out [Blazer](https://github.com/ankane/blazer/), and for advanced visualizations, check out [Vega](https://github.com/ankane/vega)
:two_hearts: A perfect companion to [Groupdate](https://github.com/ankane/groupdate), [Hightop](https://github.com/ankane/hightop), and [ActiveMedian](https://github.com/ankane/active_median)
[](https://github.com/ankane/chartkick/actions)
## Quick Start
Add this line to your application’s Gemfile:
```ruby
gem "chartkick"
```
Then follow the instructions for your JavaScript setup:
- [Importmap](#importmap) (Rails default)
- [Bun, esbuild, rollup.js, or Webpack](#bun-esbuild-rollupjs-or-webpack)
- [Sprockets](#sprockets)
This sets up Chartkick with [Chart.js](https://www.chartjs.org/). For other charting libraries and frameworks, see [these instructions](#additional-charting-libraries).
### Importmap
In `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
pin "Chart.bundle", to: "Chart.bundle.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
import "Chart.bundle"
```
### Bun, esbuild, rollup.js, or Webpack
Run:
```sh
bun add chartkick chart.js
# or
yarn add chartkick chart.js
```
And in `app/javascript/application.js`, add:
```js
import "chartkick/chart.js"
```
### Sprockets
In `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
//= require Chart.bundle
```
## Charts
Line chart
```erb
<%= line_chart User.group_by_day(:created_at).count %>
```
Pie chart
```erb
<%= pie_chart Goal.group(:name).count %>
```
Column chart
```erb
<%= column_chart Task.group_by_hour_of_day(:created_at, format: "%l %P").count %>
```
Bar chart
```erb
<%= bar_chart Shirt.group(:size).sum(:price) %>
```
Area chart
```erb
<%= area_chart Visit.group_by_minute(:created_at).maximum(:load_time) %>
```
Scatter chart
```erb
<%= scatter_chart City.pluck(:size, :population) %>
```
Geo chart - *Google Charts*
```erb
<%= geo_chart Medal.group(:country).count %>
```
Timeline - *Google Charts*
```erb
<%= timeline [
["Washington", "1789-04-29", "1797-03-03"],
["Adams", "1797-03-03", "1801-03-03"],
["Jefferson", "1801-03-03", "1809-03-03"]
] %>
```
Multiple series
```erb
<%= line_chart [
{name: "Workout", data: {"2026-01-01" => 3, "2026-01-02" => 4}},
{name: "Call parents", data: {"2026-01-01" => 5, "2026-01-02" => 3}}
] %>
```
or
```erb
<%= line_chart Feat.group(:goal_id).group_by_week(:created_at).count %>
```
## Data
Data can be a hash, array, or URL.
#### Hash
```erb
<%= line_chart({"2026-01-01" => 2, "2026-01-02" => 3}) %>
```
#### Array
```erb
<%= line_chart [["2026-01-01", 2], ["2026-01-02", 3]] %>
```
#### URL
Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
```erb
<%= line_chart completed_tasks_charts_path %>
```
And in your controller, pass the data as JSON.
```ruby
class ChartsController < ApplicationController
def completed_tasks
render json: Task.group_by_day(:completed_at).count
end
end
```
For multiple series, add `chart_json` at the end.
```ruby
render json: Task.group(:goal_id).group_by_day(:completed_at).count.chart_json
```
## Options
Id, width, and height
```erb
<%= line_chart data, id: "users-chart", width: "800px", height: "500px" %>
```
Min and max values
```erb
<%= 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.
Min and max for x-axis - *Chart.js*
```erb
<%= line_chart data, xmin: "2026-01-01", xmax: "2026-02-01" %>
```
Colors
```erb
<%= line_chart data, colors: ["#b00", "#666"] %>
```
Stacked columns or bars
```erb
<%= column_chart data, stacked: true %>
```
Discrete axis
```erb
<%= line_chart data, discrete: true %>
```
Label (for single series)
```erb
<%= line_chart data, label: "Value" %>
```
Axis titles
```erb
<%= line_chart data, xtitle: "Time", ytitle: "Population" %>
```
Straight lines between points instead of a curve
```erb
<%= line_chart data, curve: false %>
```
Hide points
```erb
<%= line_chart data, points: false %>
```
Show or hide legend
```erb
<%= line_chart data, legend: false %>
```
Specify legend position
```erb
<%= line_chart data, legend: "bottom" %>
```
Donut chart
```erb
<%= pie_chart data, donut: true %>
```
Prefix, useful for currency - *Chart.js, Highcharts*
```erb
<%= line_chart data, prefix: "$" %>
```
Suffix, useful for percentages - *Chart.js, Highcharts*
```erb
<%= line_chart data, suffix: "%" %>
```
Set a thousands separator - *Chart.js, Highcharts*
```erb
<%= line_chart data, thousands: "," %>
```
Set a decimal separator - *Chart.js, Highcharts*
```erb
<%= line_chart data, decimal: "," %>
```
Set significant digits - *Chart.js, Highcharts*
```erb
<%= line_chart data, precision: 3 %>
```
Set rounding - *Chart.js, Highcharts*
```erb
<%= line_chart data, round: 2 %>
```
Show insignificant zeros, useful for currency - *Chart.js, Highcharts*
```erb
<%= line_chart data, round: 2, zeros: true %>
```
Friendly byte sizes - *Chart.js*
```erb
<%= line_chart data, bytes: true %>
```
Specify the message when data is loading
```erb
<%= line_chart data, loading: "Loading..." %>
```
Specify the message when data is empty
```erb
<%= line_chart data, empty: "No data" %>
```
Refresh data from a remote source every `n` seconds
```erb
<%= line_chart url, refresh: 60 %>
```
You can pass options directly to the charting library with:
```erb
<%= line_chart data, library: {backgroundColor: "#eee"} %>
```
See the documentation for [Chart.js](https://www.chartjs.org/docs/), [Google Charts](https://developers.google.com/chart/interactive/docs/gallery), and [Highcharts](https://api.highcharts.com/highcharts) for more info. For Chart.js plugins, check out [this guide](guides/Chartjs-Plugins.md).
To customize datasets in Chart.js, use:
```erb
<%= line_chart data, dataset: {borderWidth: 10} %>
```
You can pass this option to individual series as well.
### Global Options
To set options for all of your charts, create an initializer `config/initializers/chartkick.rb` with:
```ruby
Chartkick.options = {
height: "400px",
colors: ["#b00", "#666"]
}
```
Customize the html
```ruby
Chartkick.options[:html] = '%{loading}'
```
You capture the JavaScript in a content block with:
```ruby
Chartkick.options[:content_for] = :charts_js
```
Then, in your layout, use:
```erb
<%= yield :charts_js %>
```
For Padrino, use `yield_content` instead of `yield`.
This is great for including all of your JavaScript at the bottom of the page.
### Multiple Series
You can pass a few options with a series:
- `name`
- `data`
- `color`
- `dataset` - *Chart.js only*
- `points` - *Chart.js only*
- `curve` - *Chart.js only*
### Code
If you want to use the charting library directly, get the code with:
```erb
<%= line_chart data, code: true %>
```
The code will be logged to the JavaScript console. JavaScript functions cannot be logged, so it may not be identical.
### Download Charts
*Chart.js only*
Give users the ability to download charts. It all happens in the browser - no server-side code needed.
```erb
<%= line_chart data, download: true %>
```
Safari will open the image in a new window instead of downloading.
Set the filename
```erb
<%= line_chart data, download: {filename: "boom"} %>
```
Set the background color
```erb
<%= line_chart data, download: {background: "#ffffff"} %>
```
Set title
```erb
<%= line_chart data, title: "Awesome chart" %>
```
## Additional Charting Libraries
- [Google Charts](#google-charts)
- [Highcharts](#highcharts)
### Google Charts
In your layout or views, add:
```erb
<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
```
For Importmap (Rails default), in `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
```
For Bun, esbuild, rollup.js, or Webpack, run:
```sh
bun add chartkick
# or
yarn add chartkick
```
And in `app/javascript/packs/application.js`, add:
```js
import "chartkick"
```
For Sprockets, in `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
```
To specify a language or Google Maps API key, use:
```js
Chartkick.configure({language: "de", mapsApiKey: "..."})
```
before your charts.
### Highcharts
For Importmap (Rails default), run:
```sh
bin/importmap pin highcharts --download
```
And in `config/importmap.rb`, add:
```ruby
pin "chartkick", to: "chartkick.js"
```
And in `app/javascript/application.js`, add:
```js
import "chartkick"
import Highcharts from "highcharts"
window.Highcharts = Highcharts
```
For Bun, esbuild, rollup.js, or Webpack, run:
```sh
bun add chartkick highcharts
# or
yarn add chartkick highcharts
```
And in `app/javascript/packs/application.js`, add:
```js
import "chartkick/highcharts"
```
For Sprockets, download [highcharts.js](https://code.highcharts.com/highcharts.js) into `vendor/assets/javascripts` (or use `yarn add highcharts`), and in `app/assets/javascripts/application.js`, add:
```js
//= require chartkick
//= require highcharts
```
### Multiple Libraries
If more than one charting library is loaded, choose between them with:
```erb
<%= line_chart data, adapter: "google" %>
```
## Sinatra and Padrino
Download [chartkick.js](https://raw.githubusercontent.com/ankane/chartkick/master/vendor/assets/javascripts/chartkick.js) and include it manually.
```html
```
Then include the charting library.
Chart.js - download [Chart.js](https://unpkg.com/chart.js@4/dist/chart.umd.js) and the [date-fns adapter bundle](https://unpkg.com/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.js)
```html
```
Google Charts
```html
```
Highcharts - download [highcharts.js](https://code.highcharts.com/highcharts.js)
```html
```
## JavaScript API
Access a chart with:
```javascript
var chart = Chartkick.charts["chart-id"]
```
Get the underlying chart object with:
```javascript
chart.getChartObject()
```
You can also use:
```javascript
chart.getElement()
chart.getData()
chart.getOptions()
chart.getAdapter()
```
Update the data with:
```javascript
chart.updateData(newData)
```
You can also specify new options:
```javascript
chart.setOptions(newOptions)
// or
chart.updateData(newData, newOptions)
```
Refresh the data from a remote source:
```javascript
chart.refreshData()
```
Redraw the chart with:
```javascript
chart.redraw()
```
Destroy the chart with:
```javascript
chart.destroy()
```
Loop over charts with:
```javascript
Chartkick.eachChart(function (chart) {
// do something
})
```
## Content Security Policy (CSP)
Check out [how to configure CSP](https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md)
## Tutorials
- [Charts with Chartkick and Groupdate](https://gorails.com/episodes/charts-with-chartkick-and-groupdate)
- [Creando gráficos en Ruby on Rails con Chartkick y Chart.js](https://www.youtube.com/watch?v=W92AlkwQn3M)
- [Make Easy Graphs and Charts on Rails with Chartkick](https://www.sitepoint.com/make-easy-graphs-and-charts-on-rails-with-chartkick/)
- [Practical Graphs on Rails: Chartkick in Practice](https://www.sitepoint.com/graphs-on-rails-chartkick-in-practice/)
## History
View the [changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md)
## Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- [Report bugs](https://github.com/ankane/chartkick/issues)
- Fix bugs and [submit pull requests](https://github.com/ankane/chartkick/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
```sh
git clone https://github.com/ankane/chartkick.git
cd chartkick
bundle install
bundle exec rake test
```
---
## File: guides/Chartjs-Plugins.md
# Chart.js Plugins
Chartkick works with Chart.js global plugins. Here’s how to add the [annotation](https://www.chartjs.org/chartjs-plugin-annotation/latest/) plugin.
For Importmaps, download the [UMD version](https://unpkg.com/chartjs-plugin-annotation@3/dist/chartjs-plugin-annotation.cjs) to `vendor/javascript`, change the extension from `.cjs` to `.js`, pin it in `config/importmap.rb`, and use:
```javascript
import "chartjs-plugin-annotation"
```
For Bun, esbuild, rollup.js, and Webpack, install the NPM package and use:
```javascript
import { Chart } from "chart.js"
import annotationPlugin from "chartjs-plugin-annotation"
Chart.register(annotationPlugin)
```
For Sprockets, download the [UMD version](https://unpkg.com/chartjs-plugin-annotation@3/dist/chartjs-plugin-annotation.cjs) to `vendor/assets/javascripts`, change the extension from `.cjs` to `.js`, and use:
```javascript
//= require chartjs-plugin-annotation
```
Then use the `library` option to apply it to charts:
```erb
<%= line_chart data, library: {plugins: {annotation: {annotations: {line1: {type: "line", yMin: 2, yMax: 2}}}}} %>
```
---
## File: guides/Content-Security-Policy.md
# Content Security Policy (CSP)
Chartkick tries to make CSP as easy as possible. Currently, `unsafe-inline` styles must be enabled for charts to work. There are open issues to resolve this with some of the charting libraries.
- [Chart.js](https://github.com/chartjs/Chart.js/issues/5208)
- [Highcharts](https://github.com/highcharts/highcharts/issues/6173)
Google Charts also requires `unsafe-eval` and as well as styles and scripts from the `https://www.gstatic.com` domain.
## Rails 5.2+
Rails 5.2+ has built-in support for CSP. Configure CSP and enable automatic nonce generation in `config/initializers/content_security_policy.rb` with:
```ruby
Rails.application.config.content_security_policy do |policy|
policy.script_src :self
policy.style_src :self
end
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
```
Enable unsafe inline styles on actions that have charts
```ruby
class ChartsController < ApplicationController
content_security_policy only: :index do |policy|
policy.style_src :self, :unsafe_inline
end
end
```
## Secure Headers
Configure CSP in `config/initializers/secure_headers.rb` with:
```ruby
SecureHeaders::Configuration.default do |config|
config.csp = {
default_src: %w('none'),
script_src: %w('self'),
style_src: %w('self')
}
end
SecureHeaders::Configuration.named_append(:charts) do |request|
{style_src: %w('unsafe-inline')}
end
```
Enable unsafe inline styles on actions that have charts
```ruby
class ChartsController < ApplicationController
def index
use_content_security_policy_named_append(:charts)
end
end
```
--- METRICS ---
- Files Extracted: 4
- Estimated Token Budget: ~6906 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/ankane/chartkick