Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
5
Help us understand the problem. What are the problem?
@kei-kun1960

[Rails] chart.jsでRailsアプリに投稿数推移グラフを描画する [chart.js]

はじめに

 このたび、Ruby on Railsの学習を始めました。まだまだ初学者ですが、日々の学びや気づき、エラーとの闘いをここに記録していきたいと思います。ご要望、ご指摘もお待ちしております!

記事の概要

 アプリで取り扱われるデータを可視化できればと思い、chart.jsを使ってRailsアプリにグラフを描いてみます。
 1. chart.jsの導入手順
 2. 記事投稿数の推移グラフを描いてみる

chart.jsとは?

 JavaScriptで実装されたグラフをRailsアプリに組込むことができるライブラリです。
 公式
 https://www.chartjs.org/docs/latest/

1. chart.jsの導入手順

 Gemfileに記述する。

Gemfile
gem 'chart-js-rails', '~> 0.1.4'

 そしてターミナルでbundle installを実行する。

% bundle install

 package.jsonに以下の通り追記。

package.json
{
  # 省略
  "dependencies": {
    #省略
    "chart.js": "^2.7.1" # ←ここに追記
  }
}

 そしてターミナルでyarn installを実行。

% yarn install

2. 記事投稿数推移グラフを描いてみる

 ここでは、とあるArticleモデルの投稿数推移について、Articlesコントローラーでデータを加工してarticles#indexにグラフ描画することをゴールとします。
 横軸が日付、縦軸が投稿数です。なお、日時データを扱う"groupdate" gemは導入済みとして進めます。

 まず、グラフ描画の基本構成は下記のようになります。公式ページのサンプル参照。

app/views/articles/index.html.erb
<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で用意しましょう。インスタンス変数を定義します。

app/controllers/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へアクセスすると縦棒グラフが描画されている。
9b48f26e7b6e328f9f4e7909036baf80.png

 次に、累計投稿数を折れ線グラフにして、先ほどのグラフに重ねてみます。

app/views/articles/index.html.erb
<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>

 累積投稿数データを配列にして、インスタンス変数として用意します。

app/controllers/articles_controller
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へアクセスすると、線グラフも表示されました。

e3ab7a129fe8fecaf3509774075090a5.png

まとめ

 chart.jsを活用し、記事投稿数推移グラフを縦棒+折れ線グラフで表現できました。データベースから加工したデータをグラフで表現することができるので、アプリの管理者機能、可視化など幅広く活用できそうです。カスタマイズも柔軟にできそうなので、今後も記事で取扱いたいと思います。
 Rubyでのデータ加工(もっと簡潔にできそう)とJavaScript記述の良いトレーニングにもなりました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
5
Help us understand the problem. What are the problem?