この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
前回構築したAngularJS+Ruby on Railsのアプリに
今回はCRUDの内のUpdate機能を実装し、ウィスキーの情報を更新する画面を作成しました。
画面遷移としては
・一覧画面(index.html.erb)よりリンクをクリックし、今回作成する更新画面(edit.html.erb)に遷移する
・更新画面でボタンを押下すると、AngularJSにより非同期でサーバを呼び出し、更新する
・登録後、AngularJSにより一覧画面に遷移する
となります。
以下に、実装する上でのポイントとなる箇所を記述していきます。
尚、ソースコードは以下のGitHubに置いてあるので、全ソースを見たい方は参考にしてください。
AngularjsWhiskyList
実装について
1.ルーティング
更新画面に表示するデータを取得するためのURLとして、以下のコードをroutes.rbに追記します。
get 'whiskies/:id/detail' => 'whiskies#detail'
$ rake routes でルーティングの確認をすると、以下のようになります。
whiskies_list GET /whiskies/list(.:format) whiskies#list
GET /whiskies/:id/detail(.:format) whiskies#detail
(中略)
edit_whisky GET /whiskies/:id/edit(.:format) whiskies#edit
whisky GET /whiskies/:id(.:format) whiskies#show
PATCH /whiskies/:id(.:format) whiskies#update
PUT /whiskies/:id(.:format) whiskies#update
DELETE /whiskies/:id(.:format) whiskies#destroy
今回使用するのは
・更新画面に表示するデータを取得する「GET /whiskies/:id/detail(.:format) whiskies#detail」(2行目)
・更新画面に遷移するための「GET /whiskies/:id/edit(.:format) whiskies#edit」(4行目)
・更新データを送るための「PUT /whiskies/:id(.:format) whiskies#update」(7行目)
です。
2.一覧画面
一覧画面に、更新画面へ遷移するためのリンクと、削除するためのボタンを追加しました。
またTwitter Bootstrapのtableを使い、多少見栄えを良くしています。
(尚、今回は削除ボタンについては触れません)
index.html.erb
<h1>Whiskies#index</h1>
<%= link_to "new whisky", new_whisky_path, :class => 'btn btn-mini' %>
<table ng-controller="WhiskiesCtrl" class="table">
<tr ng-repeat="whisky in data">
<td>{{whisky.name}}</td>
<td>${{whisky.price}}</td>
<td><a href="/whiskies/{{whisky.id}}/edit" class="btn btn-mini">Edit</a></td>
<td><button ng-click="Delete(whisky);" class="btn btn-mini">Delete</button></td>
</tr>
</table>
EditリンクのURLの定義は「a href="/whiskies/{{whisky.id}}/edit」となっています。
{{whisky.id}}はAngularJSの式で、{{}}内に記述した変数やプロパティ等の値を参照します。
ここでは一覧に表示するデータのidが取得されるので、実際のURLは以下のような形となります。
/whiskies/2/edit
上記1.で記述した、更新画面に遷移するためのURLを指定していることが分かるかと思います。
3.更新画面
更新画面は以下のようになります。
edit.html.erb
<h1>Whiskies#edit</h1>
<div ng-controller="WhiskiesEditCtrl">
<div>Name</div><div><input type="text" ng-model="data.name"></div>
<div>Price</div><div><input type="text" ng-model="data.price"></div>
<button ng-click='Update();' class="btn-primary">Update</button>
</div>
ここでは
・AngularJSの「WhiskiesEditCtrl」コントローラを呼び出す
・テキストボックスに「data.name」「data.price」を初期表示する
・Updateボタン押下時に「Update()」を呼び出す
を行っています。
4.更新処理のAngularJS
更新画面から呼び出されるAngularJSは、以下のようになります。
controllers.js
whiskiesListApp.controller('WhiskiesEditCtrl', function ($scope, $http, $window) {
$http.get('detail').success(function(data) {
$scope.data = data;
}).error(function(data, status) {
console.log('error:' + status);
});
$scope.Update = function(){
$http.put('/whiskies/' + $scope.data.id, {'name': $scope.data.name, 'price': $scope.data.price}
).success(function(data, status, headers, config) {
$window.location.href = '/';
}).error(function(data, status) {
console.log('error:' + status);
});
}
});
更新画面から呼び出される「WhiskiesEditCtrl」コントローラは
・「$http.get('detail').success(function(data) {・・・」のデータ取得処理
・「$scope.Update = function(){・・・」のUpdateボタン押下時の処理
の2つに分かれます。
「$http.get('detail').success(function(data) {・・・」のデータ取得処理は
上記1.で記述した、データを取得するURLを指定しています。
先に説明したように、更新画面自体は「/whiskies/:id/edit」の形で呼び出されています。
このURLの末尾「edit」を「detail」に変えることで、「/whiskies/:id/detail」となり
ルーティングで定義されているデータを取得するためのURLとなります。
「$scope.Update = function(){・・・」のUpdateボタン押下時の処理は
上記1.で記述した、更新データを送るためのURLを指定しています。
ここで注目して欲しいのは、「$http.put」でPUT送信している点です。
PUT送信することで、ルーティングで定義されているデータを更新するためのURLとなります。
※Railsのコントローラのdetail()、update()アクションについては
単純なActiveRecordのソースとなります。詳細はGitHub上のソースを参考にしてください。
最後に
以上です。
AngularJSの$httpオブジェクトを使うことで、Railsのルーティングに即したURLを生成し
処理を行うことができました。