Rails Charts
One more gem to build nice charts for your Ruby on Rails application.
With it you can build various types of charts Apache eCharts library (v. 5.4.0). This gem simplifies interface and adding few helpers to start adding charts in your app with just a few lines of code.
What you can build with it:
- area chart
- line chart
- bar chart
- donut chart
- pie chart
- radar chart
- calendar chart
- candlestick chart
- funnel chart
- gauge chart
- parallel chart
- sankey chart
- scatter chart
- stacked bar chart
- custom chart
In most cases with one line of code you can have a nice chart. The idea of this gem was inspired by Chartkick gem which is great and allows you to build charts very quickly. It works best in cooperation with groupdate gem. Unfortunatelly it's missing many needed types of charts or other customization options.
This implementation have more options and similar "interface" for building charts.
Installation
Add gem to your application's Gemfile:
gem "rails_charts"
Then execute:
$ ./bin/bundle install
You can install ECharts with installation command
$ ./bin/rails rails_charts:install
or do it manualy
Sprockets
- add eCharts in main JS bundle, e.g.
app/assets/javascripts/application.js
//= require echarts.min.js
//= require echarts/theme/dark.js
- add your first chart e.g.
<%= line_chart User.group(:age).count %>
- customize charts if needed. See available options or official documentation.
Webpack / esbuild
- Run:
yarn add echarts
For Rails 7
- In
app/javascript/application.js
add this:
import * as echarts from 'echarts';
import 'echarts/theme/dark';
window.echarts = echarts;
For Rails 6
- In
app/javascript/packs/application.js
add this:
import * as echarts from 'echarts';
import 'echarts/theme/dark';
window.echarts = echarts;
- add your first chart e.g.
<%= line_chart User.group(:age).count %>
- customize charts if needed. See available options or official documentation.
Importmaps
- change
config/importmap.rb
pin "echarts", to: "echarts.min.js"
pin "echarts/theme/dark", to: "echarts/theme/dark.js"
- add eCharts in main JS
import "echarts"
import "echarts/theme/dark"
- add your first chart e.g.
<%= line_chart User.group(:age).count %>
- customize charts if needed. See available options or official documentation.
Options
<%= line_chart data, {
width: '250px',
height: '250px',
theme: 'dark',
class: 'chart-container-class',
style: 'padding: 10px'
} %>
Available options:
width: specify width of the chart
height: specify height of the chart
theme: specify theme of the chart (available themes examples https://echarts.apache.org/en/download-theme.html)
class: specify container's CSS class
id: specify container's ID
style: add inline style
debug: for gem development useful if you want to pause somewhere in the code
vertical: applicable for some types of charts
code: to see output code what is generated to see the chart, useful for debugging
options: {...}, nested hash, specify additional eCharts options
Apache eCharts options - https://echarts.apache.org/en/option.html#title.
If you need to format tooltip (or other javascript function as an option) you can pass a JS function, but you need to wrap it like:
options: {
tooltip: {
valueFormatter: RailsCharts.js("(value) => '$' + Math.round(value)")
}
}
Charts
All examples available in https://github.com/railsjazz/rails_charts/tree/main/test/dummy/app/views/home. You can see more examples if you clone this repo and start a dummy app.
Every chart has a built in default configuration for tooltips, or other options (sample https://github.com/railsjazz/rails_charts/blob/main/lib/rails_charts/line_chart.rb#L64-L75). This is just to simplify usage of this gem. In the future the plan is to have it configured in initializer.
Area Chart
<%= area_chart User.distinct.pluck(:role).map{|e| {name: e, data: User.where(role: e).group_by_day(:created_at).count} } %>
Line Chart
<%= line_chart User.group(:age).count, class: 'box',
options: {
title: {
text: "People count by age",
left: 'center'
},
}
%>
Bar Chart
<%= bar_chart User.group(:role).average(:age),
class: 'box',
theme: 'sakura',
options: {
series: {
barWidth: '50%'
},
tooltip: {
valueFormatter: RailsCharts.js("(value) => '$' + Math.round(value)")
}
}
%>
Calendar Chart
<%= calendar_chart Commit.for_calendar_chart,
class: 'box',
options: {
visualMap: {
show: true,
min: 0,
max: 40,
orient: 'horizontal'
},
calendar: [{
range: '2021',
},]
}
%>
Candlestick Chart
<%= candlestick_chart({
'2017-10-24' => [20, 34, 10, 38],
'2017-10-25' => [40, 35, 30, 50],
'2017-10-26' => [31, 38, 33, 44],
'2017-10-27' => [38, 15, 5, 42]
},
class: 'box',
theme: 'roma',
options: {
xAxis: {
axisTick: {
alignWithLabel: true
}
}
})
%>
Funnel Chart
<%= funnel_chart User.get_funnel_sample_data,
class: 'box',
height: '400px',
options: {
title: {
text: 'Demo',
left: 'center'
}
}
%>
Gauge Chart
<%= gauge_chart User.get_gauge_sample_data,
class: 'box',
height: '400px',
options: {
title: {
text: 'Demo',
left: 'center'
}
}
%>
Parallel Chart
<div class="box">
<%= parallel_chart [
[1, 2, 1, "Ruby"],
[2, 3, 2, "JavaScript"],
[3, 1, 3, "C#"]
], {
options: {
parallelAxis: [
{ dim: 0, name: '2019', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },
{ dim: 1, name: '2020', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },
{ dim: 2, name: '2021', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },
{ dim: 3, type: "category", name: 'Language', data: ["Ruby", "JavaScript", "C#"], inverse: true, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 14 } },
]
}
}
%>
</div>
Donut Chart
<%= donut_chart User.group(:role).count,
class: 'box',
options: {
legend: {
bottom: '0'
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
%>
Pie Chart
<%= pie_chart User.group(:role).count,
class: 'box',
options: {
legend: { orient: 'vertical', left: 'left' }
}
%>
Radar Chart
<%= radar_chart User.get_data_for_radar_chart,
class: 'box',
options: {
legend: {
data: ['Average Salaries', 'Maximum Salary'],
orient: 'vertical',
left: '20%'
}
}
%>
Sankey Chart
<%= sankey_chart({
data: [
{name: 'Ruby'}, {name: 'HTML'}, {name: 'JS'}, {name: 'Good'}, {name: 'Bad'}, {name: 'CSS'}, {name: 'PHP'}, {name: 'Frontend'}, {name: 'Backend'}
],
links: [
{
source: 'Ruby',
target: 'Good',
value: 1
},
{
source: 'HTML',
target: 'Good',
value: 1
},
{
source: 'JS',
target: 'Good',
value: 1
},
{
source: 'CSS',
target: 'Good',
value: 1
},
{
source: 'PHP',
target: 'Bad',
value: 1
},
{
source: 'Good',
target: 'Backend',
value: 1
},
{
source: 'Good',
target: 'Frontend',
value: 3
},
{
source: 'Bad',
target: 'Backend',
value: 1
},
]
}, {
options: {
}
})
%>
Scatter Chart
<%= scatter_chart [
{ name: 'John', data: User.random_scatter_chart(500, 200) },
{ name: 'Bob', data: User.random_scatter_chart(500, 1000) },
],
{
class: 'box',
options: {
xAxis: {
name: 'Distance'
},
yAxis: {
name: 'Sales'
},
legend: {
data: [
{name: 'John'},
{name: 'Bob'},
]
},
},
}
%>
Stacked bar Chart
<%= stacked_bar_chart [
{ name: 'high priority', data: Account.high_priority.group_by_month(:created_at, format: "%b %Y").count },
{ name: 'low priority', data: Account.low_priority.group_by_month(:created_at, format: "%b %Y").count }
],
{
options: {
title: {
text: "Popular vs Unpopular"
},
},
class: 'box',
vertical: true
}
%>
Custom Chart
<%= custom_chart {...raw JS options ...} %>
Contributing
You are welcome to contributes. Some open tasks:
- support turbo streams?
- add more specs
- add more examples to the dummy app
- customization, options overides, default values?
- every "5sec" refresh
- remote data
- how to access chart from JS
- better documentation how to specify theme, locale, etc
- more examples with data structure
- add github actions
- add info about initializer and it's configuration
- specify info about default configs per chart
- add support for CSP similar to https://github.com/ankane/chartkick/blob/master/lib/chartkick/helper.rb#L55
- example of how to build multiple-chart charts
Development and testing
test/dummy/bin/rails s
- to start dummy app.
rspec
- to run specs.
License
The gem is available as open source under the terms of the MIT License.
Gem is using https://echarts.apache.org/ to build charts.