11 分のあれに 5 分くらいでウェブサービス API を追加するシナリオ
http://itoshi.tv/d/?date=20060506#p01 に ActionWebService (AWS) をつかってウェブサービス API を追加してみた.タイプするだけなら 5 分くらいでできるシナリオである.
- http://itoshi.tv/d/?date=20060506#p01
- http://manuals.rubyonrails.com/read/chapter/67 AWDwR の Chapter 20 Web Services on Rails を参考にした.
Agile Web Development With Rails: A Pragmatic Guide (The Facets Of Ruby Series)
- 作者: David Thomas,David Heinemeier Hansson,Leon Breedt
- 出版社/メーカー: Pragmatic Bookshelf
- 発売日: 2005/09/22
- メディア: ペーパーバック
- クリック: 18回
- この商品を含むブログ (56件) を見る
- http://idm.s9.xrea.com/ratio/2006/04/17/000414.html が AWS の雰囲気をつかむのに大変参考になった.
仕様
今回のウェブサービス API の仕様は,データベースのエントリを ID で取得したり,ID のリストを取得する基本的で簡単なものを考える.
- API 名:Expression
- affyid の発現量を取得するメソッド:find_expressions_by_id(affyid)
- 引数 affyid は String
- 返り値は Float の Array
- affyid の任意の day の発現量を取得するメソッド:find_expression_by_id(affyid, day)
- 引数 affyid は String
- 引数 day は Int
- 返り値は Float
- affyid のリストを取得するメソッド:find_all_affyid
- 引数はなし
- 返り値は String の Array
次に,ウェブサービスのためのコードを生成する.なお,以降の作業は実働する11 分のあれのディレクトリ expview の中でおこなう.
ruby script/generate web_service Expression find_expression_by_id find_expressions_by_id find_all_affyids
仕様にもとづいて API 定義 app/api/expression_api.rb を埋める.
生成された状態.
class ExpressionApi < ActionWebService::API::Base api_method :find_expression_by_id api_method :find_expressions_by_id api_method :find_all_affyids end
こうする.
class ExpressionApi < ActionWebService::API::Base api_method :find_expression_by_id, :expects => [{:affyid => :string}, {:day => :int}], :returns => [:float] api_method :find_expressions_by_id, :expects => [{:affyid => :string}], :returns => [[:float]] api_method :find_all_affyids, :expects => [], :returns => [[:string]] end
expects に引数の名前と型情報,returns に返り値の型情報を Hash の形で記述する.DSL 風味.
つぎに,仕様にもとづいて API のコントローラ app/controllers/expression_controller.rb を書く.
生成された状態.
class ExpressionController < ApplicationController wsdl_service_name 'Expression' def find_expression_by_id end def find_expressions_by_id end def find_all_affyids end end
こうする.
class ExpressionController < ApplicationController wsdl_service_name 'Expression' web_service_scaffold :invoke def find_expression_by_id(affyid, day) @expression = Expression.find_by_affyid(affyid) if [0, 2, 4, 10].include?(day) @expression["d#{day}"] else -1.0 end end def find_expressions_by_id(affyid) @expression = Expression.find_by_affyid(affyid) ['d0', 'd2', 'd4', 'd10'].map {|m| @expression[m] } end def find_all_affyids Expression.find(:all).map {|x| x.affyid } end end
サーバの起動と web service scaffold で動作確認
ruby script/server open http://localhost:3000/expression/invoke
app/controllers/expression_controller.rb の web_service_scaffold :invoke によって,ウェブサービスのクライアントが提供されている.なお,open コマンドは Mac OS X 付属のものである.
ここで注意する必要があるのは find_all_affyids() は返り値が非常に大きいため,レンダリングに非常に多くのリソースを必要とするのでブラウザが固まりがち.invoke ボタンをクリックしてはいけない.
これくらいの API だったら 5 分くらいでタイプできるでしょう.
SOAP::WSDLDriver をつかったクライアント
SOAP::WSDLDriver をつかったクライアントの例.ウェブサービスで利用できるメソッドは methods(false) で調べることができる.
require 'soap/wsdlDriver' wsdl_uri = "http://localhost:3000/expression/service.wsdl" factory = SOAP::WSDLDriverFactory.new(wsdl_uri) driver = factory.create_driver method_list = driver.methods(false) p method_list #=> ["findExpressionsById", "FindAllAffyids", "findAllAffyids", "FindExpressionById", "findExpressionById", "FindExpressionsById"] expression = driver.findExpressionById("100015_at", 0) p expression #=> 5.55660043997955 expression = driver.send("FindExpressionById", "100015_at", 0) p expression #=> 5.55660043997955 expressions = driver.findExpressionsById("100015_at") p expressions #=> [5.55660043997955, 5.6629197160292, 5.60480888509297, 5.72528846920502] affyid_list = driver.findAllAffyids() p affyid_list #=> ["100001_at", "100002_at", "100003_at", ...