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



## 目的
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_at`と`data`の２つを取得する。取得した情報をインスタンス変数に格納する。最後に`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は２次元配列を指定する必要があるので、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](https://qiita-image-store.s3.amazonaws.com/0/43219/dbbb7a09-296a-c9ad-2e18-ce5bdce72298.png "Highchartsグラフ.png")

## お世話になったサイト
- Javascriptプログラミング解説Dateオブジェクト
http://www.crystal-creation.com/web-app/tech/programming/javascript/grammar/object/date.htm#no115

- 放射線量可視化(4)：Highcharts JSのグラフによる可視化
http://fromto.cc/hosokawa/diary/2011/20111204-home2/

- highcharts x軸を日付にするノウハウ
http://blogs.yahoo.co.jp/montabross/67516003.html