はじめに
このたび、Ruby on Railsの学習を始めました。まだまだ初学者ですが、日々の学びや気づき、エラーとの闘いをここに記録していきたいと思います。ご要望、ご指摘もお待ちしております!
記事の概要
アプリで取り扱われるデータを可視化できればと思い、chart.jsを使ってRailsアプリにグラフを描いてみます。
1. chart.jsの導入手順
2. 記事投稿数の推移グラフを描いてみる
chart.jsとは?
JavaScriptで実装されたグラフをRailsアプリに組込むことができるライブラリです。
公式
https://www.chartjs.org/docs/latest/
1. chart.jsの導入手順
Gemfileに記述する。
gem 'chart-js-rails', '~> 0.1.4'
そしてターミナルでbundle installを実行する。
% bundle install
package.jsonに以下の通り追記。
{
# 省略
"dependencies": {
#省略
"chart.js": "^2.7.1" # ←ここに追記
}
}
そしてターミナルでyarn installを実行。
% yarn install
2. 記事投稿数推移グラフを描いてみる
ここでは、とあるArticleモデルの投稿数推移について、Articlesコントローラーでデータを加工してarticles#indexにグラフ描画することをゴールとします。
横軸が日付、縦軸が投稿数です。なお、日時データを扱う"groupdate" gemは導入済みとして進めます。
まず、グラフ描画の基本構成は下記のようになります。公式ページのサンプル参照。
<canvas id="myChart" width="200" height="100"> </canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar', # 'bar'でグラフタイプを縦棒グラフに指定
data: {
labels: <%= @chartlabels %>, # 横軸にとるデータ(今回は投稿日付)を埋め込む
datasets: [{
label: "投稿数",
data: <%= @chartdatas %>, # 縦軸にとるデータ(今回は投稿数)を埋め込む
backgroundColor: 'rgba(255, 80, 120, 1.0)',
borderColor: 'rgba(255, 80, 120, 1.0)',
fill: false
}]
},
});
</script>
グラフに渡すデータをarticles_controllerで用意しましょう。インスタンス変数を定義します。
class ArticlesController < ApplicationController
def index
@articles = Article.all
@article_by_day = @articles.group_by_day(:created_at).size
# groupdateのgroup_by_dayメソッドで投稿日(created_at)に基づくグルーピングして個数計上。
# => {Wed, 05 May 2021=>23, Thu, 06 May 2021=>20, Fri, 07 May 2021=>3, Sat, 08 May 2021=>0, Sun, 09 May 2021=>12, Mon, 10 May 2021=>2}
@chartlabels = @article_by_day.map(&:first).to_json.html_safe
# 投稿日付の配列を格納。文字列を含んでいると正しく表示されないので.to_json.html_safeでjsonに変換。
# => "[\"2021-05-05\",\"2021-05-06\",\"2021-05-07\",\"2021-05-08\",\"2021-05-09\",\"2021-05-10\"]"
@chartdatas = @article_by_day.map(&:second)
# 日別投稿数の配列を格納。
# => [23, 20, 3, 0, 12, 2]
end
end
Railsアプリを起動し/indexへアクセスすると縦棒グラフが描画されている。
次に、累計投稿数を折れ線グラフにして、先ほどのグラフに重ねてみます。
<canvas id="myChart" width="200" height="100"> </canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: <%= @chartlabels %>,
datasets: [{
label: "日別投稿数",
data: <%= @chartdatas %>,
backgroundColor: 'rgba(255, 80, 120, 1.0)',
borderColor: 'rgba(255, 80, 120, 1.0)',
fill: false
},{ //ここから追記
label: "累積投稿数",
data: <%= @cumulative %>, // 縦軸にとる累積投稿数データを埋め込む
backgroundColor: 'rgba(255, 80, 120, 0.2)',
borderColor: 'rgba(255, 80, 120, 1.0)',
type: 'line', // 'line'でグラフタイプを折線グラフに指定
}]
},
});
</script>
累積投稿数データを配列にして、インスタンス変数として用意します。
class ArticlesController < ApplicationController
def index
@articles = Article.all
@article_by_day = @articles.group_by_day(:created_at).size
@chartlabels = @article_by_day.map(&:first).to_json.html_safe
@chartdatas = @article_by_day.map(&:second)
# ここから追記
@cumulative = []
sum=0
@chartdatas.each do |a|
sum = sum + a
@cumulative<<sum
end
end
end
アプリを起動し/indexへアクセスすると、線グラフも表示されました。
まとめ
chart.jsを活用し、記事投稿数推移グラフを縦棒+折れ線グラフで表現できました。データベースから加工したデータをグラフで表現することができるので、アプリの管理者機能、可視化など幅広く活用できそうです。カスタマイズも柔軟にできそうなので、今後も記事で取扱いたいと思います。
Rubyでのデータ加工(もっと簡潔にできそう)とJavaScript記述の良いトレーニングにもなりました。