Pages

2011年8月20日土曜日

iPhoneアプリ(Titunium)からWebアプリ(Ruby on Rails)へのデータ転送

TutorialのTwitterアプリでWeb API経由でデータを取得する方法の勘所をつかんだので、iPhoneからWebアプリへのデータのアップロードを試してみる。

Webアプリケーション

Webアプリ側は、手っ取り早く Ruby On Railsで作成。
(Railsのヴァージョンは、2.3.8を入れてあるので、databaseのdefaultは、sqlite3)
Webアプリのイメージは、在庫管理用の商品コードの保管と表示。モデルは、在庫Stock。StockをiPhone側から扱うコントローラは、Apiと言う名前にした。
$ rails testapp
$ cd testapp
$ script/generate model Stock
$ script/generate controller Api index

"Stock" modelのmigrationの中身は、以下の感じ
  1. create_table :stocks do |t|  
  2.     t.string :name # 商品名 今回は、無用。  
  3.     t.string :code # 商品コード  
  4.     t.timestamps  
  5. end  
create_table :stocks do |t|
	t.string :name # 商品名 今回は、無用。
	t.string :code # 商品コード
	t.timestamps
end

controllerの中身は、WebAPI的なのりで作成してみた。APIの仕様?は以下の通り。
http://hogehoge/api/               --- 全てをjson形式で提供(表示)
http://hogehoge/api/show/code_no   --- コード = code_no のstockをjsonで提供
http://hogehoge/api/upload/code_no --- 新しいデータを登録 code = code_no

例外処理とか未だ入れてないので、エラー頻発だ。

  1. class ApiController < ApplicationController  
  2.     # 全て表示のアクション  
  3.     def index  
  4.         @stocks = Stock.all  
  5.         # レスポンスは、jsonにフォーマットして出力  
  6.         respond_to do |format|  
  7.             format.json { render :json => @stocks:callback => params[:callback] }  
  8.         end  
  9.     end  
  10.   
  11.     # 商品コードを指定して出力  
  12.     def show  
  13.         @stock = Stock.find_by_code(params[:id])  
  14.         respond_to do |format|  
  15.             format.json { render :json => @stock:callback => params[:callback] }  
  16.         end  
  17.     end  
  18.   
  19.     # 今回の主役。商品コードを受け取り、データベースに保管する  
  20.     # レスポンスは、textにした  
  21.     def upload  
  22.         message = 'Upload Error'  
  23.         if params[:id] && stock = Stock.new({:code => params[:id]})  
  24.             message = 'Save New Code :' + stock.code if stock.save  
  25.         end  
  26.         render :text => message  
  27.     end  
  28. end  
class ApiController < ApplicationController
    # 全て表示のアクション
	def index
		@stocks = Stock.all
		# レスポンスは、jsonにフォーマットして出力
		respond_to do |format|
			format.json { render :json => @stocks, :callback => params[:callback] }
		end
	end

	# 商品コードを指定して出力
	def show
		@stock = Stock.find_by_code(params[:id])
		respond_to do |format|
			format.json { render :json => @stock, :callback => params[:callback] }
		end
	end

	# 今回の主役。商品コードを受け取り、データベースに保管する
	# レスポンスは、textにした
	def upload
		message = 'Upload Error'
		if params[:id] && stock = Stock.new({:code => params[:id]})
			message = 'Save New Code :' + stock.code if stock.save
		end
		render :text => message
	end
end

これで、script/server でテストサーバを起動。
http://hogehoge:3000/api/ を試してみた。確かにjson形式で出力されている。


Titunium側のプログラム(一部)

さて、Tituniumアプリ側の該当部分。HTTPClientオブジェクトを操作する。

  1. var win = Ti.UI.currentWindow;  
  2. var sendButton = Ti.UI.createButton({  
  3.     title:'Send Data',  
  4.     top:200,  
  5.     left:10,  
  6.     width:300,  
  7.     height:100  
  8. });  
  9. win.add(sendButton);  
  10.   
  11. // sendボタンのclickイベントを記述  
  12. sendButton.addEventListener('click'function(){  
  13.     // HTTPClientオブジェクトを用意  
  14.     var xhr = Ti.Network.createHTTPClient();  
  15.     xhr.timeout = 1000000;  
  16.     var sample = '12345'// サンプルデータ  
  17.     var url = 'http://hogehoge:3000/api/upload/' + sample;  
  18.     xhr.open('GET',url);  
  19.     // ロードされた場合の処理を記述。  
  20.     // ここではレスポンスを受け取ってダイアログボタンに結果を返すと定義。  
  21.     xhr.onload = function(){  
  22.         var res = this.responseText;  
  23.         Ti.UI.createAlertDialog({  
  24.             title: 'Send Data',  
  25.             message: res  
  26.         }).show();  
  27.     };  
  28.     // リクエストを送信する。レスポンスが帰ったときに、onloadアクションとなる。  
  29.     xhr.send();  
  30. });  
var win = Ti.UI.currentWindow;
var sendButton = Ti.UI.createButton({
	title:'Send Data',
	top:200,
	left:10,
	width:300,
	height:100
});
win.add(sendButton);

// sendボタンのclickイベントを記述
sendButton.addEventListener('click', function(){
	// HTTPClientオブジェクトを用意
	var xhr = Ti.Network.createHTTPClient();
	xhr.timeout = 1000000;
	var sample = '12345'; // サンプルデータ
	var url = 'http://hogehoge:3000/api/upload/' + sample;
	xhr.open('GET',url);
	// ロードされた場合の処理を記述。
	// ここではレスポンスを受け取ってダイアログボタンに結果を返すと定義。
	xhr.onload = function(){
		var res = this.responseText;
		Ti.UI.createAlertDialog({
	  		title: 'Send Data',
	  		message: res
	  	}).show();
	};
	// リクエストを送信する。レスポンスが帰ったときに、onloadアクションとなる。
	xhr.send();
});

iPhoneアプリをエミュレータで起動。[send]ボタンを押すと、サーバアプリにサンプルデータが送信され、その結果がモーダルボタンで表示される。

気になったこと
  • ボタンイベントに変数(この場合はデータ)を渡す方法
  • HTTPClientの接続失敗の処理方法
  • send()のタイミングは、正しいか?

0 件のコメント:

コメントを投稿