Alloy Modelの学習・その4(REST API)
引き続き、Alloy Modelを勉強中。
クロスプラットフォームなUIを素早く構築しつつWeb APIと連携するというのは、Titaniumが活用できるパターンだと思います。
というわけで、今回はREST APIとのData Bindingを試してみました。
REST API Sync Adapter
標準で用意されているSync Adapterは、SQLite用のSql AdapterとTitanium.App.Propertiesを使うProperties Adapterの2種類しかありませんが、Sync Adapterは自作することもできます。
Custom Sync Adapters - Alloy Sync Adapters and Migrations
REST API用のSync Adapterを作ってくれている人がいますので、これを採用することにします。
viezel/napp.alloy.adapter.restapi
今回作るもの
アプリ自体は簡単にするため、 その2 で作ったものと同じ仕様とします。
それとは別に、連携先のAPIが必要です。
適当なWeb APIを使っても良かったのですが、CRUDを一通り触りたかったのと、サーバー側に渡ってくるリクエストの内容も把握したかったので、今回はスタブAPIサーバーを立てることにしました。
スタブAPIサーバー
スタブAPIサーバーについては、シンプルで使いやすそうだったMockyを使ってみることにしました。
okv/mocky: http mocking server with simple config written on nodejs
テーブル
スタブなので実際のデータベースは用意しませんが、 その2 と同じ仕様ということで、以下のようなテーブル構造を扱うAPIを用意します。
内容 | カラム | 型 |
---|---|---|
レコードの識別子 | id | INTEGER |
メモの内容 | contents | TEXT |
メモの優先度 | priority | TEXT |
API
上記のテーブルをもとに、CRUDをひととおり呼び出せるよう、以下のようなAPIにすることにしました。
操作 | Method | URL |
---|---|---|
メモを読み込む | GET | http://127.0.0.1:4321/memos |
メモを追加 | POST | http://127.0.0.1:4321/memos |
メモの内容を更新 | PUT | http://127.0.0.1:4321/memos/{ID} |
メモを削除 | DELETE | http://127.0.0.1:4321/memos/{ID} |
スタブAPIPサーバー自体の実装は省略しますが、ダミーデータをメモリ上に保持しておいて、APIの呼び出しに合わせてダミーデータを操作しています。
例えばメモの読み込みAPIを叩くと、こんな感じにJSONのレスポンスを得られる感じです。
データベースを使っていないので、サーバーを再起動するとデータは初期状態に戻ります。
ソースは umi-uyura/AlloyModelStudyRestStub にありますので、こちらをご覧ください。
Qiitaにあった mocky を使ってちょっと賢いスタブAPIサーバを作る - Qiita や Node.js の mocky を使用し スタブREST API を作成してみる、その1 - Qiita あたりを読めば簡単に作れました。
アプリ
アプリ側のソースは umi-uyura/AlloyModelStudyRestApi です。
プロジェクト作成
毎度おなじみCLIでプロジェクト作成。
$ titanium create --type app --id com.example.titanium.alloymodelstudyrestapi --name AlloyModelStudyRestApi --platforms iphone,android --url http://www.example.com --workspace-dir . $ alloy new AlloyModelStudyRestApi
これをベースに、今回もUIはJade & Stylusに、FokkeZB/UTiL/xp.ui を使っています。
REST API Sync Adapter (napp.alloy.adapter.restapi) の準備
GitHubのリポジトリから restapi.js をダウンロードして、プロジェクト内の app/assets/alloy/sync/
へ配置しておきます。
モデル作成
先の想定テーブル構造から、ベースとなるモデルを生成します。このとき、 restapi
タイプというのは Alloy
コマンドがサポートしていないため、いったん sql
として生成しました。
$ alloy generate model memo sql 'id:integer' contents:text priority:text
生成されたモデルファイルをもとに、REST API用に編集します。
exports.definition = { config: { columns: { "id": "integer", "contents": "text", "priority": "text" }, adapter: { type: "restapi", collection_name: "memo", "idAttribute": "id" }, "URL": "http://127.0.0.1:4321/memos", "debug": 1 }, extendModel: function(Model) { _.extend(Model.prototype, { }); return Model; }, extendCollection: function(Collection) { _.extend(Collection.prototype, { comparator: function(data) { return (0 - data.get('priority').length); } }); return Collection; } };
編集した箇所としては、以下のとおりです。
config.adapter.type
をrestapi
に変更URL
を追加し、スタブAPIのURLを設定debug
を追加、これでAPIを使う際のリクエスト/レスポンスがデバッグ出力されてわかりやすい
他に headers
や parentNode
をといった設定もありますが、今回は未使用。
以下はデバッグ出力の例。
Data Binding
ビューの部分は 前回 と同じもので、コントローラもほぼ一緒で動きました。
一箇所修正したのは、メモを追加したあとに呼び出していた memos.fetch()
の部分で、通信が発生してタイミングが変わるせいか、これを呼び出してしまうと追加したはずのメモが消えてしまう現象が発生しました。
その上の行の memos.add(m)
までで、ListViewには新しいメモが追加されていたので、 memos.fetch()
は削除することにしました。
app/controllers/index.js
... function addText() { var txt = $.memoText.getValue(); var params = { contents: txt, priority: '' }; var m = Alloy.createModel('memo', params); m.save(); memos.add(m); //memos.fetch(); <== 削除した $.memoText.setValue(''); } ...
エラーハンドリングについて
今回やっていないこととして、通信のエラーハンドリングがあります。
データ構造を同じにしたこともありますが、SQL用からREST API用にAdapterを入れ替えて、ほぼそのまま動かせてしまいました。
しかし、ローカルにあるデータベースなどと比べて、インターネットを介した通信は不安定だったり、APIサーバー側で何らかの問題が発生することなども考えられます。
そのため、napp.alloy.adapter.restapiには、以下のような感じで通信成功時とエラー時で処理をハンドリングできるようになっています。
var collection = Alloy.createCollection("MyCollection"); //or model //the fetch method is an async call to the remote REST API. collection.fetch({ success : function(){ _.each(collection.models, function(element, index, list){ // We are looping through the returned models from the remote REST API // Implement your custom logic here }); }, error : function(){ Ti.API.error("hmm - this is not good!"); } });
napp.alloy.adapter.restapiを使ってきちんと実装する場合は、この点も考慮する必要があると思います。
参考
- viezel/napp.alloy.adapter.restapi
- AlloyのModelでREST APIからデータを取得する - Qiita
- Titanium + Alloy + napp.alloy.adapter.restapiで作る簡単Qiitaビューワーアプリ - Qiita
- Titanium + Alloy + napp.alloy.adapter.restapiで作る簡単Qiitaビューワーアプリ応用編(ページネーション機能の実装) - Qiita
モックサーバー
- okv/mocky: http mocking server with simple config written on nodejs
- mocky を使ってちょっと賢いスタブAPIサーバを作る - Qiita
- Node.js の mocky を使用し スタブREST API を作成してみる、その1 - Qiita
- 【図解】RESTful WebサービスにおけるHTTPステータスコード : アジャイル株式会社
Appcelerator Titanium Smartphone App Development Cookbook - Second Edition
- 作者: Jason Kneen
- 出版社/メーカー: Packt Publishing
- 発売日: 2015/11/30
- メディア: Kindle版
- この商品を含むブログを見る