Backbone.js版ToDoMVCアプリのバックエンドをGrails REST APIに変更する

Grails2.3から加わったRESTful APIを提供する機能を使って、Backbone.js版ToDoMVCアプリのバックエンドをlocalStorageからGrails REST APIに変更してみます。

出来たやつ:https://github.com/geekduck/restapp のcommit 4f577884f97db839eb986385c2ed3bb4e96aca2b

環境

  • Grails 2.3.4
  • ToDoMVC 1.2.0
  • Backbone.js 1.0.0

Grailsアプリを作成

grails create-app restapp

ToDoMVCアプリの配置、起動確認

http://todomvc.com/ からアプリをダウンロードし、適当な場所に展開します。(ここでは~/Downloads/tastejs-todomvc-b29e998に展開しました)

Backbone.js版のToDoMVCアプリをGrailsアプリのweb-app/backboneに配置します。

cp ~/Downloads/tastejs-todomvc-b29e998/architecture-examples/backbone restapp/web-app

Grailsを起動し、ToDoMVCアプリを実行してみます。

cd restapp
grails

grails> run-app

http://localhost:8080/restapp/backbone/ にアクセスすると、ToDoMVCアプリが表示されます。

この段階ではブラウザのlocalStorageにtodoのデータが格納されます。以降でバックエンドをGrailsのRESTful APIで置き換えていきます。

ToDoドメインを作成、RESTful APIとして公開

クライアント側のモデル(web-app/backbone/js/models/todo.js)に対応するドメインGrails側で作成します。

Grailsが起動中の場合は停止しておきます。

grails> stop-app
grails> create-domain-class Todo

作成したToDoドメインを編集します。

package restapp

import grails.rest.Resource

@Resource(uri='/todos', formats=['json', 'xml'])
class Todo {
    String title
    Boolean completed

    static constraints = {
    }
}

ここでドメインクラスに@Resourceアノテーションを付与しておくと、以下の表のようなURIマッピングと各URIに対応するController Actionを自動で作成してくれます。

HTTP Method URI Controller Action
GET /todos index
GET /todos/create create
POST /todos save
GET /todos/${id} show
GET /todos/${id}/edit edit
PUT /todos/${id} update
DELETE /todos/${id} delete

RESTful APIのテストデータをBootStrap.groovyに追加しておきます。

import restapp.Todo

class BootStrap {

    def init = { servletContext ->
        new Todo(title:"aaa", completed: false).save()
        new Todo(title:"bbb", completed: false).save()
    }
    def destroy = {
    }
}

Grailsアプリを起動してブラウザでhttp://localhost:8080/restapp/todos にアクセスすると、Bootstrap.groovyで追加したテストデータのJSONリストが表示されます。

サーバー側の準備はこれで完了です。

ToDoMVCアプリのバックエンドをRESTful APIに修正

Todo Collection(web-app/backbone/js/collections/todos.js)からlocalStorageを使用している一行を削除し、サーバー側のRESTful APIURIを返すurlメソッドを定義します。

diff --git a/web-app/backbone/js/collections/todos.js b/web-app/backbone/js/collections/todos.js
index db7b6a5..739c21b 100755
--- a/web-app/backbone/js/collections/todos.js
+++ b/web-app/backbone/js/collections/todos.js
@@ -7,14 +7,16 @@ var app = app || {};
     // Todo Collection
     // ---------------

-    // The collection of todos is backed by *localStorage* instead of a remote
-    // server.
+    // The collection of todos is backed by grails server.
     var Todos = Backbone.Collection.extend({
         // Reference to this collection's model.
         model: app.Todo,

-        // Save all of the todo items under the `"todos"` namespace.
-        localStorage: new Backbone.LocalStorage('todos-backbone'),
+        // REST API URL
+        url: function () {
+            return '/restapp/todos';
+        },
+

         // Filter down the list of all todo items that are finished.
         completed: function () {
~

クライアント側で変更しなければならない点は上記の1箇所だけですが、web-app/backbone/index.html から不要なJS(base.js、backbone.localStorage.js)を参照したままなので削除しておきます。

diff --git a/web-app/backbone/index.html b/web-app/backbone/index.html
index 745960d..31c0df7 100755
--- a/web-app/backbone/index.html
+++ b/web-app/backbone/index.html
@@ -51,11 +51,9 @@
     <button id="clear-completed">Clear completed (<%= completed %>)</button>
     <% } %>
 </script>
-<script src="bower_components/todomvc-common/base.js"></script>
 <script src="bower_components/jquery/jquery.js"></script>
 <script src="bower_components/underscore/underscore.js"></script>
 <script src="bower_components/backbone/backbone.js"></script>
-<script src="bower_components/backbone.localStorage/backbone.localStorage.js"></script>
 <script src="js/models/todo.js"></script>
 <script src="js/collections/todos.js"></script>
 <script src="js/views/todo-view.js"></script>

これでクライアント側の修正は完了です。

動作確認

grailsを起動して、http://localhost:8080/restapp/backbone/ にアクセスします。

Bootstrap.groovyで追加したテストデータが最初から表示されているはずです。

データベースを確認してみましょう。

http://localhost:8080/restapp/dbconsole/ をブラウザで開き、JDBC URLに「jdbc:h2:mem:devDb」を入力しConnectします。

そこからToDoドメインに対応するデータベースのテーブルを参照できるので、クライアント側で新規作成や更新、削除を行いデータベースが更新されているのを確認します。

まとめ

今回のToDoドメインのように単純なCRUD操作を行うようなAPIであれば、Grailsの場合は5行程度でRESTful APIを公開できるので楽で良いですね!

参考資料

Grails本家:http://grails.org/doc/latest/guide/webServices.html#REST

上記の日本語訳:http://grails.jp/doc/latest/guide/webServices.html#REST

id:yamkazuさんのハンズオン資料:https://github.com/yamkazu/jggug-nov-2013-grails23