Help us understand the problem. What is going on with this article?

【Rails】個人開発のアプリにGitHub風のチャートを実装

More than 1 year has passed since last update.

個人開発のWebアプリまちかどルート」v6.2に、名づけて《アクティビティ・チャート》なるものを実装したときのメモです。

参考記事

こちらの記事を参考にさせていただきました。
ありがとうございます!

Railsアプリで Cal-Heatmap を表示してみる
https://qiita.com/volpe28v/items/3a5a2c05f1c0ee3fa5ad

以下、じぶんなりのアレンジも含めてメモとして残します。

view

\app\views\layouts\application.html.erb
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cal-heatmap/3.6.2/cal-heatmap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cal-heatmap/3.6.2/cal-heatmap.css" />

レイアウトテンプレートのapplication.html.erbにこの3行を書き加えることで、今回必要なライブラリ「D3.js」と「Cal-heatmap」を読み込ませています。

\app\views\users\show.html.erb
<div id="heatmap"></div>
<script>
    var startDate = new Date();
    startDate.setMonth(startDate.getMonth() - 5);

    var parser = function(data) {
        return eval("(" + data + ")");
    };

    var cal = new CalHeatMap();
    cal.init({
        itemSelector: "#heatmap",
        data: "/api/v1/comments?user_id=<%= @user.id %>&start=<%= Time.now.ago(6.months) %>&stop=<%= Time.now %>",
        afterLoadData: parser,
        cellSize: 5,
        domain: "month",
        subDomain: "day",
        range: 6,
        tooltip: false,
        start: startDate,
        domainLabelFormat: "%b",
        legend: [1,2,3,4],
        weekStartOnMonday: false,
        legendVerticalPosition: "center",
        legendOrientation: "vertical"
    });
</script>

公式のドキュメントを参考にしながらcal.init({ })内の各種オプションを指定しています。また、前述の参考記事と違うのは、とくにdataの部分です。下記のAPIに渡すパラメーターのstartstopTime.nowメソッドを使うことで、APIから取得するJSONデータの期間(ここでは6か月分)を指定しています。

API

\app\api\resources\v1\comments.rb
module Resources
  module V1
    class Comments < Grape::API
      resources :comments do

        # /api/v1/comments
        desc 'アクティビティ・チャートJSON出力'
        params do
          requires :user_id, type: Integer, desc: 'ユーザーID'
        end
        get do
          user = User.find(params[:user_id])
          from = params[:start]
          to = params[:stop]

          comments1 = Post.where(post_uid: user.uid, created_at: from..to)
          comments2 = Comment.where(user_uid: user.uid, created_at: from..to)
          comments1 = comments1.to_a
          comments2 = comments2.to_a
          comments = comments1 + comments2
          comments.map{|c| c.created_at.to_i}.inject(Hash.new(0)){|h, tm| h[tm] += 1; h}.to_json
        end

      end
    end
  end
end

わたしのアプリでも、ちょうど参考記事と同じくGrapeを使ってAPIを構築しています。

参考記事と違うのはPostCommentというふたつのテーブルにある投稿日時のカラムcreated_atを抽出&結合し、アクティビティ・チャートに反映させている点です。

課題

参考記事にも書かれていますが「rails から json で返したデータをパースするメソッドを定義して afterLoadData に設定する(eval しないと json として読み込めなかったので)」とのこと。

確かにこれをしないとチャートが表示されません。

しかしながら、このせいか、ログを見るといちどに2回、APIを叩いています。

Started GET "/api/v1/comments?user_id=1&start=2018-12-18%2009:57:23%20+0900&stop=2019-06-18%2009:57:23%20+0900" for 192.168.14.1 at 2019-06-18 09:57:23 +0900
  [1m[36mUser Load (0.1ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m  [["id", 1], ["LIMIT", 1]]
  ↳ app/api/resources/v1/comments.rb:12
  [1m[36mPost Load (0.2ms)[0m  [1m[34mSELECT "posts".* FROM "posts" WHERE "posts"."post_uid" = ? AND "posts"."created_at" BETWEEN ? AND ?[0m  [["post_uid", "townsguild@another-guild.com"], ["created_at", "2018-12-18 09:57:23"], ["created_at", "2019-06-18 09:57:23"]]
  ↳ app/api/resources/v1/comments.rb:18
  [1m[36mComment Load (0.1ms)[0m  [1m[34mSELECT "comments".* FROM "comments" WHERE "comments"."user_uid" = ? AND "comments"."created_at" BETWEEN ? AND ?[0m  [["user_uid", "townsguild@another-guild.com"], ["created_at", "2018-12-18 09:57:23"], ["created_at", "2019-06-18 09:57:23"]]
  ↳ app/api/resources/v1/comments.rb:19
Started GET "/api/v1/comments?user_id=1&start=2018-12-18%2009:57:23%20+0900&stop=2019-06-18%2009:57:23%20+0900" for 192.168.14.1 at 2019-06-18 09:57:23 +0900
  [1m[36mUser Load (0.2ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m  [["id", 1], ["LIMIT", 1]]
  ↳ app/api/resources/v1/comments.rb:12
  [1m[36mPost Load (0.7ms)[0m  [1m[34mSELECT "posts".* FROM "posts" WHERE "posts"."post_uid" = ? AND "posts"."created_at" BETWEEN ? AND ?[0m  [["post_uid", "townsguild@another-guild.com"], ["created_at", "2018-12-18 09:57:23"], ["created_at", "2019-06-18 09:57:23"]]
  ↳ app/api/resources/v1/comments.rb:18
  [1m[36mComment Load (0.6ms)[0m  [1m[34mSELECT "comments".* FROM "comments" WHERE "comments"."user_uid" = ? AND "comments"."created_at" BETWEEN ? AND ?[0m  [["user_uid", "townsguild@another-guild.com"], ["created_at", "2018-12-18 09:57:23"], ["created_at", "2019-06-18 09:57:23"]]
  ↳ app/api/resources/v1/comments.rb:19

なんとかして1回で済むようにviewの<script>data-turbolinks-eval=falseを追記したり、いろいろ試したのですが解決できていません。

まだまだ未熟です...。
これからも精進していきたいと思います。

west2538
40代でセミリタイアして中山間地域の豪雪地帯に新しい住まいの形「ギルドハウス十日町」を設立。そこでWebアプリ「まちかどルート」を開発しています
https://machiroute.herokuapp.com/
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした