Categories
open all | close allTags
アクセス制御 | スキンエンジン | JustPosted | Subversion | テスト | 名称 | 国際化 | モデル | タグ | フォーム | Migration | パソコン | rake | CSRF | Aptana | デュアル・コア | Flash | ドキュメント | 認証 | RESTfulSearch
REST化についての考察(まとめ)
ここではRucleus(仮称)でなぜRESTの設計を取り入れることにしたのか,どういう問題があるのかをまとめておきます。RESTの意味とそのメリット
Rails 2.0の目玉の一つがRESTfulな設計が簡単になったことですが,RESTの機能自体はRails 1.2で導入されています。僕自身は「RESTってWebサービスのインタフェースの1つでSOAPほど面倒くさくないやつでしょ」ってくらいの認識しかなかったのですが,RESTについて調べると,そういうものではなくてWebアプリケーションの設計思想に近いものだということが分かってきました。
RESTfulなアプリケーションやサービスではURLはリソースを示します。例えばブログやアイテムがリソースです。Railsではモデルすなわちデータベースのテーブルがリソースになります。これに対して「何をするか」という「アクション」はHTTPのverb,すなわち「GET」や「POST」などで表現します。これをリソースのコントローラに対して適用します。つまり,モデルのクラス1つに対してコントローラのクラス1つが対応するような形になります。なおverbとしてHTTPの仕様では「DELETE」,「PUT」(データの更新)が定義されていますが,現在使われているブラウザが送信するのはGETとPOSTしかないため,Railsではフォームに特別なフィールドを作ってDELETE,PUTを実現します。
RESTのもう1つの特徴に内部状態に依存しないということがあります。クッキーやセッション・データによって表示内容を変えることがなく,URL(正確に言えば,HTTPヘッダに含まれる情報)で結果が決まります。これによって,ページ・キャッシュが実現しやすいというメリットがあります。サーバーに内部情報を保存する必要がないため分散処理も容易になります。
また,「respond to」による各種フォーマットのサポートという特徴もあります。例えばRailsのRESTサポートではXMLによる出力を標準的に利用できるようになっています。
これらRESTの特徴はNucleus(Rucleus)となじみがいいものです。例えば,初期の設定ではURLの解釈においてアプリケーションというコントローラにブログやカテゴリーといったリソースの情報を渡して「item」をアクションとしてIDを付けてアクセスするといった形にしていました。それよりはブログやアイテムをリソースとしてアクセスすると考えた方がすっきりします。また2番目の特徴は性能を考えたときにクリティカルになってきます。最後の各種フォーマットのサポートも,スキンを切り替えることでさまざまな出力を行うNucleusのスタイルと相性がいいです。
認証の問題
では,何が問題になって悩んでいたかというと,認証関係とURL周りです。まず,認証ですが,RESTではNucleusが従来やっているようなクッキーを使った認証というのは問題になります。BASIC認証やダイジェスト認証,WSSE認証といったHTTPで定められた認証が必要です。この中でWSSE認証はブラウザがサポートしていないため,JavaScriptでなにやらやる必要があるなど,採用には問題点があります。次にBASIC認証やダイジェスト認証を使ったときですが,いくつかの課題が生じます。①1つのURLでログイン・ユーザーとゲストで違ったページを表示するのが難しい,②ログイン時にダイアログ・ボックスが出るのが格好悪い,独自のページでログインさせたい,③ログアウトが困難,といったものです。
こちらのページにはこれらの条件を満足させてダイジェスト認証を使う方法が記載されていますが,詳しく読んでみると,ブラウザによってやり方を変えなければいけないなど,現実に採用するには難しい部分がかなりありそうです。上の問題で①が機能的に一番ほしいところですが,逆に言えばここだけ我慢すればいいという見方もできます。
URLの問題とその解決法
最後の問題となったのがURL周りです。冒頭に書いたようにRails 2.0ではREST対応のアプリケーションを簡単に作れるようになっていますが,URLに大きな制限を受けてしまいます。例えば,blogidが1のitemidが10というアイテムにアクセスする場合,URLは「blog/1/item/10」といった形式に固定化されてしまいます。ここを独自のURL設計にする方法が分からずに悩んでいたわけです。
現在のURL周りの処理はこんな感じです。例えば /blogname でブログにアクセスする場合
map.blog ':blogname', :controller => "blogs", :action => 'show'といった形で「blogs」をコントローラにしてshowというアクションを実行します。blognameからブログを見つける処理はshowの中に記述します。これに各種フォーマット対応をするために次のように追加します。
map.blog ':blogname.:format', :controller => "blogs", :action => 'show'アプリケーションのコントローラには
private
def setblog
if !params['blogname']
$NCGlobals['blog'] = Blog.find(CONF['DefaultBlog'])
else
$NCGlobals['blog'] = Blog.find_by_bname(params['blogname']) || Blog.find(CONF['DefaultBlog'])
end
end
def setcatid
if params['catid']
$NCGlobals['catid'] = params['catid'].to_i
end
end
def setskin(skinname)
if (skinname=='')
$NCGlobals['skin'] = $NCGlobals['blog'].skin
else
skin = Skin.find_by_sdname(skinname)
$NCGlobals['skin'] = (skin) ? skin :$NCGlobals['blog'].skin
end
end
public
def blog(skinname='')
setblog
setcatid
setskin(skinname)
$NCGlobals['skintype'] = 'index'
$NCGlobals['item'] = Array.new
$NCGlobals['controller'] = self
@contents = $NCGlobals['skin'].part($NCGlobals['skintype'])
@controller = NCParser::DefaultSkinIndex.new $NCGlobals['controller']
render :action=>'index.html.erb'
end
といった形でblognameから実際のブログオブジェクトを見つけることなどが記述されます。また,blogs_controllerのshowメソッドは
def show
respond_to do |format|
format.html { blog }
format.xml { blog('feeds/rss20') }
end
endといった形になります。このようにしておくだけで /lab.xml というURLでアクセスするとRSS2.0のフィードを生成してくれるようになります。
Comments
No comments yet. You can be the first!