
バックエンドがRuby on Railsの場合に、vue.jsでデータベースのデータを操作したい場合の話です。
1レコード分だけ取得するのであれば、インスタンス変数「@で始まる変数」にそれぞれ値を入れて渡すだけでもいいのですが、複数レコード(もしくは全レコード)を一気にjavascript側に持ってきたい場合もあります。
今回はRailsの機能ベースで部分的にvue.jsを使うシチュエーションで進めていきます。
目次
複数レコードを一気に持ってくるメリットは?
まず、複数レコード(全レコード)を一回で持ってくるメリットを考えてみましょう。
1.vue.jsのv-forが使える
「v-for」は同じ要素をデータ分だけ繰り返し表示させたい時に便利な文法です。
データベースに登録されているデータの数だけ繰り返し表示が出来るメリットがあります。
例として、僕が作っているAnybookの問題集一覧表示を見てみましょう。
問題集リストをv-forを使ってデータの数だけ表示させています。
これを実現するには、テーブルのデータを配列もしくはオブジェクト形式でデータを取得する必要があります。
2.通信回数を最小限に抑えられる
SPAサイトを作成している場合は特に動きが止まりにくい、スムーズなデータのやり取りが好ましいので、
頻繁にデータを取りに行くのはあまりいいとは言えません。(場合にもよります)
javascript側にデータがあれば、ID検索もjavascriptで行えますので、サーバーのやり取りは最初の1回で事足ります。
実際につくってみよう!
では実際にどのように作ればいいのか、説明します。
1.ActiveRecoadで取得したデータをオブジェクト化する
あるテストの成績テーブルを取得する場合で考えていきます。
【seisekiテーブル】
id | kamoku | point |
---|---|---|
1 | 国語 | 65 |
2 | 算数 | 70 |
3 | 理科 | 80 |
4 | 社会 | 50 |
これをActiveRecoadでデータを取得した後、javascriptで扱えるようにJSON化させます。
1 2 3 |
def get_seiseki @seiseki = Seiseki.all.to_json end |
モデルデータは「.to_json」でデータをJSON化させることができます。
不要なカラムがある場合、または特定のカラムだけに絞る場合、以下のようにして省くことができます。
1 2 3 4 5 |
# id, pointを省く Seiseki.all.to_json(except: [:id, :point]) # id, pointのみ取り出す Seiseki.all.to_json(only: [:id, :point]) |
たったこれだけでモデルをJSON化できるのはメチャ便利!!
JavaScriptでモデルデータを受け取る
上で作成したモデルデータを格納したインスタンス変数「@seiseki」をjavascript側で受け取ります。
Ajax通信で受け取る場合は「~.js.erb」、ビューで受け取る場合は「~.html.erb」に処理を記述します。
今回はビューで受け取る方で説明します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<script> // グローバル変数にモデルデータを格納する var modeldata = modeljson_parse('<%=@seiseki%>'); /** * モデルをJSON.parseする */ function modeljson_parse(item) { item = JSON.stringify(item); item = item.substr(1, (item.length - 2)); item = unEscapeHtml(item); item = JSON.parse(item); return item; } // アンエスケープ処理 export function unEscapeHtml(str) { str = str.replace(/(>)/g, '>'); str = str.replace(/(<)/g, '<'); str = str.replace(/(\)/g, '\\'); str = str.replace(/(")/g, '"'); str = str.replace(/(')/g, "'"); str = str.replace(/(&)/g, '&'); return str } </script> <div id="app"> HTMLソース ・ ・ ・ </div> <script> var app = new Vue({ el: '#app', data: { seiseki: modeldata } }); </script> |
グローバル変数「modeldata」にRailsからのインスタンス変数を代入します。
その時、JSONデータを「JSON.stringify」で文字列化して「JSON.parse」再度JSON化する加工を行っています。
(これをやらずにそのまま値を代入すると、処理が固まってしまった・・・)
これで、javascript側にモデルデータを引き継ぐことが出来ました!
javascriptで使ってみる
v-forでの使い方
通常のv-forの使い方と同じです。
モデルデータを格納しているdata項目を設定するだけです。
1 2 3 4 5 |
<div v-for="item in seiseki" v-bind:key="item.id"> <span>{{ item.id }}</span> <span>{{ item.kamoku }}</span> <span>{{ item.point }}</span> </div> |
モデルデータのID検索方法
取得したモデルデータのID検索用メソッドを作ります。
1 2 3 4 5 6 7 8 9 10 11 |
/** * モデル内ID検索関数(1 レコードヒット検索) * 引数: モデル, ID * 戻り値: ヒットした1レコード */ function find_model(model, id) { var result = model.filter(function (val) { return val.id == id; }); return result[0]; } |
filterで特定のレコードを絞り込んでいます。
使い方はこんな感じです。
1 2 3 4 |
var data = find_model(app.seiseki, 1); console.log(data.kamoku); // "国語" console.log(data.point); // 65 |
この関数を使えば、Railsのモデルクラスのような感覚で「data.kamoku」とキーを指定すれば値が取り出せます。