LoginSignup
19
19

More than 5 years have passed since last update.

DBに保存されているデータをHighchartsを使っていい感じのグラフを表示する

Posted at

目的

Rubyの簡易サーバSinatraを立ち上げて、DBに蓄積されているデータをHighchartsを使ってグラフ化するまでのメモ。センサが定期的にSinatraサーバにデータをPostして、webからアクセスした時に蓄積したデータをグラフ表示で見ることを想定。

フォルダ構成

erbはviewsに、jsはpublicに入れるのがsinatraの決まり事。
highchartsは公式サイトからダウンロードしましょう。

/ 
│  app.rb
│  
├─ views
│    index.erb
│
└─ public
     highcharts.js

データベース構成

データベースはこんな感じ。
datatypeとdataのカラムを用意して、センサ種類を定義しながら一括でDB管理できるようにした。datatypeごとにdataを取得してグラフ化していく。

id datatype data created_at updated_at
1 abc 12 2014-05-21 12:17:38 UTC ***
2 abc 123 2014-05-20 13:20:16 UTC ***
3 abc 123 2014-05-18 12:11:39 UTC ***

前提

SinatraでデータをPost/DeleteしてDB操作を行う方法は、以下のHPを参考にして作りました。ここでは割愛。データがあることを前提に、erbにデータを渡して、JavascriptのHighchartsを使ってグラフ化していく。

・Sinatra+ActiveRecord+SQLite3で,軽量なWeb-DB連携例
http://tamosblog.wordpress.com/2012/10/26/sinatra/

Sinatra-ActiverecordでDB情報を取得する

Rubyメインのapp.rbで、DB情報をソートして、datatype=abcのレコードのうち、created_atdataの2つを取得する。取得した情報をインスタンス変数に格納する。最後にindex.erbを呼び出す。そんなに複雑なことはしない。

app.rb
require 'rubygems'
require 'sinatra'
require 'sinatra/reloader'
require 'active_record'

# ActiverecordのORマッピング
# ENV['DATABASE_URL']はお使いの環境に合わせましょう
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL']) 
class Sensor < ActiveRecord::Base
end

# Sinatraメイン
get '/' do
  @sensor_abc = Sensor.order("id").where(:datatype => "abc").select("created_at", "data")

  erb :index
end

JavascriptでHighchartsのdataを生成する

index.erbの中のJavascriptの中で、インスタンス変数を使ってデータを取得する。
Highchartsのdataは2次元配列を指定する必要があるので、Array関数に代入してく。
Highchartsを時系列表示は、時間をUTC指定にする必要があるので注意。ここでは、getTime()を使ってUTCにしている。あと、時間降順に並べないとバグります。降順はruby側でソートしている。

index.erb(抜粋)
<script type="text/javascript">
・・・

var val = new Array();
<% @sensor_abc.each do |abc|%>
    var ary = new Array();

    var time = new Date("<%= abc.created_at %>");
    ary.push(time.getTime());   // getTimeでUTCに変換
    ary.push(<%= abc.data.to_f %>); // Stringデータを実数にする。
    val.push(ary);
<%end%>

・・・
</script>

Highchartsでグラフ化する

Highchartsのソースは以下。seriesのdataに上記で作成したval変数を指定すればOK。
x軸の時間をローカルタイムにしています。

index.erb(抜粋)
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="./highcharts.js"></script>


<script type="text/javascript">
    var chart;

    // 表示をUTCからローカルタイムにする
    Highcharts.setOptions({
        global : {
            useUTC : false
        }
    });

    function draw() {
        // グラフオプションを指定
        var options = {
            // 出力先を指定
            chart : {
                renderTo : "container",
                type : "line",
                backgroundColor : "white"
            },
            // タイトルを指定
            title : {
                text : "abcデータ"
            },
            // x軸のラベルを指定
            xAxis : {
                type : 'datetime',
                title : {
                    text : "時間"
                }
            },
            // y軸のラベルを指定
            yAxis : {
                title : {
                    text : "数値"
                }
            },
            // データ系列を作成
            series : [{
                name : "data",
                data : val
            }]
        };
        // グラフを作成
        chart = new Highcharts.Chart(options);
    }

    // ページがロードされた後に、グラフを出力する
    document.body.onload = draw();
</script>

こんな感じになります。
Highchartsグラフ.png

お世話になったサイト

19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19