Rails とウェブサービス(Rails 勉強中 #7)

Rails とウェブサービスについては、川o・-・)<2nd life - ActionWebServiceでxmlrpcサービスを作る で詳しく解説されておりますので、俺の出る幕なんかないわけですが、Rails 本 の通りにしてもうまく動かなかったところがあるのでその回避方法のメモと、gorou さんのところに書かれていないもので、面白いものがあったのでここでとりあげてみます。

Rails 本のサンプルでは、以下のような2つのファイルを作っています。

class ProductApi < ActionWebService::API::Base
  api_method :find_all_products,
             :returns => [[:int]]
  api_method :find_product_by_id,
             :expects => [:int],
             :returns => [Product]
end
class BackendController < ApplicationController
  wsdl_service_name 'Backend'
  web_service_api ProductApi
  web_service_scaffold :invoke

  def find_all_products
    Product.find(:all).map{ |product| product.id }
  end

  def find_product_by_id(id)
    Product.find(id)
  end
end

太字の web_service_scaffold :invoke がポイントです。こいつを設定しておくと、http://host/controller/invoke で以下のような画面が表示されます。

こんな感じで、定義されているメソッド、返り値型、引数型が一覧で表示されます。さらに、各メソッドはリンクになっているので、辿ってみると以下のような画面が表示されます。

Protocol: では、SOAP か XML-RPC が選択できます。(つまり、ActionWebService は SOAP と XML-RPC の両方に勝手に対応してくれる!)また、メソッドで定義されている引数型と数に応じて、入力フォームが表示されます。で、引数に適当に値を入れて「Invoke」を押すと、以下のような画面となります。

こんな感じで、返り値(Product オブジェクト)と、リクエスト/レスポンス XMLの内容を表示してくれます。ただし、実際にブラウザからリクエスト XMLを送っているわけではないようです。post されたパラメータをそのままメソッドに渡してるみたい。なので厳密なテストにはなりませんが、どいういったメソッドがあるのかとか、各メソッドの返り値型、引数型、リクエスト/レスポンス XMLの内容 なんかがすぐに分かるので、利用者側にはすごく便利ですね。上の例は SOAP ですが、XML-RPC を選択すれば、XML の内容も XML-RPC に合わせたものになります。

さらに便利なことに、WSDL も自動生成してくれて、http://host/controller/service.wsdl でアクセスできます。なので、Ruby であれば SOAP4R で WSDL からメソッドやデータ構造を自動生成、って感じで、ウェブサービスを利用する開発者にはとてもおいしいですね。(WSDL や SOAP4R については、たださんの日記の 第八回XML開発者の日Yahoo! デベロッパーネットワーク で知りました。)

あと、本の通りにやってもうまく動かなかった点について。上のスクリーンショットで実行している、SOAP での FindProductById メソッドの実行ですが、「 can't modify frozen object 」というエラーが出ます。で、なんだかよくわからんのですが、/usr/local/lib/ruby/1.8/xsd/qname.rb の74行目の

EMPTY = QName.new.freeze

EMPTY = QName.new

に変えたら動くようになりました。でも、この変更によってどういう影響があるのか自分にはよく分かりません…