« 2008年03月 | メイン | 2008年06月 »

2008年04月18日

[Rails] RESTクライアントの認証を動的に切り替える。

こんにちわ。ばたっちです。

RESTアプリケーションはステートレスなので、認証が必要な場合は毎回リクエスト毎に認証が必要になります。

認証方法は HTTP Basic認証が推奨?されていて、Rails 2.0では Basic認証機能が強化(追加?)されてるようですね。

クライアント側でのリソースの参照に ActiveResourceを使う場合は、サイトのURLにユーザ名、パスワードを追加しておけばOKです。

こうしておけば、リクエスト時に Authorizationヘッダを追加してくれるんですね。

ところで、この site属性はクラススコープなので、リソース単位に一意になるんですが、複数のアカウントで切り替えたい場合(普通はないのかな?)にちょっと困ります。

ActiveResourceでは siteのURLを元に、connection属性(これもクラススコープ)を作っているようなので、これをいじればいいのかもしれません。

別の方法として、headers属性(ハッシュ、クラススコープ)というのがあって、ここにヘッダを追加しておくと、リクエスト送信時にヘッダに追加してくれるようです。

ということは、ここに Authorizationヘッダを追加してやれば、動的に認証情報を設定できるのかも。。

というわけで、以前作った MultiModelScope(see. [Rails] 複数のモデルに with_scope。)を真似て、MultiResourceScopeというのを作ってみました。

複数のリソースにまたがって、動的に認証を切り替えたいという場合に使えます。

こんなカンジに使うことを想定。

認証方法を変えられるようにしたり便利かも。A^^;

パターンウィーバーの韓国語版

韓国語版を開発しました。

5月ぐらいには、配布できるようになると思います。

画面ショットは、こんな感じです。


class.jpg

2008年04月16日

[Rails] RESTなサーバ/クライアントを試してみる。

こんにちわ。ばたっちです。

Rails 2.0の REST対応はは、RESTアプリのサーバ側の機能と、クライアント側の機能が入ってるんですね。

  • サーバ側 : ActionController::Resourcesとか
  • クライアント側 : ActiveResource
サーバ側では config/routes.rbに「map.resource :entry」のように書くだけで、CRUDな URLを生成してくれます。

例えば、コントローラで、

とすれば、Entryオブジェクト(ActiveRecord)を自動で XMLに変換して返します。
(ActiveRecordの to_xmlの結果をそのまま返すみたい。だからテンプレート不要。)

一方 ActiveResourceは、クライアント側で RESTで提供されているリソースを、まるで ActiveRecordのオブジェクトのように扱えるようにしてくれるクラス。

例えば、上記の showアクションのレスポンスとして、

のようなXMLを返す RESTアプリがあって、それを ActiveResourceで扱うと、

こんなカンジでアクセスできます。find()の裏では「GET /entries/1.xml」のように HTTP GETしてるんですね。
うーん、すごい。

さて、Railsが自動で作ってくれる CRUDなインターフェースがそのまま使えれば、とても便利なのですが、実際に RESTアプリを作ると考えると、少し工夫が必要になりそうです。

例えば、

  • クライアントの認証が必要な場合は?
  • ActiveRecordの idをプライマリキーにしない場合は?
という場合はどうするんだろといったカンジ。

まず、認証については、アカウント名+パスワードで認証するのであれば、URLにアカウント名、パスワードを含めてBASIC認証にするみたい。

なるほど。
ちなみに RESTの定義としてセッションなどにログイン情報を持たず、毎回のリクエストでリソースの参照を完結すべきだそうで、認証が必要な場合は認証情報も毎回送る形になるようです。

それから、APIキーを発行するだけのような場合、URLの後ろに「api_key=key1」のようにクエリパラメータをつけるのは RESTっぽくない気がするので、

http://api.example.com/api/key1/entries/1.xml

のように、URLのプレフィクスに入れる方法を考えてみました。
この場合では、ActiveResourceの siteにプレフィクスまでを含めた URLを設定すればできるようです。

次に、idをそのままプライマリキーに使えない場合。

例えば、外部の固定リソース(郵便番号情報とか)の上に RESTアプリをかぶせたりする場合、idをキーにすると外部リソースとの連携がしづらい。
例の Entryを日付をキーにしてとるような URLを考えてみる。

/api/key1/entries/20080415_001.xml

サーバ側では、config/routes.rbには以下のように設定します。
(ただし、Routing::RouteBuilderには、先日のエントリの修正をいれています。see. [Rails] routingの namespace。)

EntriesController#showには、{ :key => "key1", :action => "show", :date => "20080415_001" } のようなパラメータが渡されるので、うまく検索できるように実装します。(^^;

クライアント側では、この URLだと ActiveResourceの find(1)のような方法では取得できないのですが、ActiveRecordの findと同様、いろいろできちゃうのが find()メソッド。(^^)v

ActiveResource::Base#findメソッドには、:fromというパラメータで URLを直接指定することができるようです。 したがって、

のようにアクセスすることができます。
ちなみに、:fromパラメータには Request-URIを先頭から指定しないといけないようで、self.site に設定したプレフィクスには続けてくれないようです。

のようなメソッドを作るとよさそうですね。

他にも、element_pathという URLを作成するメソッド?があるので、そちらも使えそう。
Request-URIのプレフィクスが有効になるようです。
(こちらは逆に .xmlが勝手についてしまうので、外す方法が分かりません。A^^;)

以下はサーバとクライアントのログ。

サーバ側

クライアント側

プロセス間通信の実験みたい(プロセス間通信だけど)で面白い♪

でも、まだまだ試行錯誤ですねぇ~ (^^)/~

2008年04月14日

[Trac] TracGanttCalendarプラグイン for Trac-0.10(trac-ja)

こんにちわ。ばたっちです。

tidusさんの TracGanttCalendarというプラグインの Trac-0.10対応。

[Trac]TracGanttCalendarプラグイン
http://tidus.ultimania.org/diary/?date=20071020#p01


カレンダーとチケットの連携と、ガントチャートの描画ができるようになるプラグインです。
オリジナルは 0.11以降にのみ対応なのですが、インタアクト製の trac-ja(Trac-0.10.4)な環境で使いたかったので、移植してみました。

ロジック部分は 0.10と 0.11でそれほど変更なさそうなので、軽い気持ちで着手したら、テンプレートエンジンが ClearSilverってやつから、Genshiってのに変更になってて、実は差分がでかいということを知り、えらい目に会いました。A^^;

TracGanttCalendar 0.1(2008/4/12現在、trunkから取ってきた最新)をベースにしています。
(バージョンのつけ方がよく分からないので、0.0.1としています。)


以下、インストール方法です。

ファイルをダウンロード。
TracGanttCalendar 0.0.1

ファイルを展開。
> tar zxvf ganttcalendar-XXX.tar.gz

eggファイルを作る。
> cd ganttcalendar-XXX/
> python setup.py bdist_egg

eggファイルを pluginフォルダにコピー。
> cp dist/TracGanttCalendarPlugin-XXX-pyXX.egg /path/to/tracprj/plugins/

Apache再起動。
# /etc/init.d/apache restart

インストールが完了したら、トップのナビゲーションバーに、「カレンダー」と「ガント」が追加されます。


いまさら、0.10対応なんて必要な人いないかもしれないけど、どうぞ。A^^;


追記 (2008/4/24):
カレンダーのマイルストーン表示にエラーがあったので、修正版をアップしました。
(上のリンクからダウンロード可)


追記 (2008/4/25):
TracGanttCalendarのリポジトリにブランチ作成してもらいました♪
http://svn.sourceforge.jp/svnroot/shibuya-trac/plugins/ganttcalendarplugin/branches/0.10/

下記のコマンドでチェックアウトできます。


svn co http://svn.sourceforge.jp/svnroot/shibuya-trac/plugins/ganttcalendarplugin/branches/0.10/ ganttcalendarplugin

2008年04月09日

[Rails] routingの namespace。

こんにちわ。ばたっちです。

routing周りのコード見ていて気になったんですが。。
(Railsのバージョンは 2.0.1)

という部分は、

となるのが正しいんじゃないかと。。A-_-;;

  • namespace -> コントローラのプレフィクス
  • path_prefix -> URLのプレフィクス
  • name_prefix -> URL名のプレフィクス
と考えるとすっきりするんだけどなぁ。

routingのテストには path_prefixありのケースがない(resourcesにはたくさん)ようなので、どうあるべきかが分かりません。。うーん。A^^;

2008年04月02日

[Rails] 複数のモデルに with_scope。

こんにちわ。ばたっちです。

複数のモデルに対してあるカラムでフィルタリングしたい(ローカライズとか)と思って、ActiveRecordの with_scopeを調べてみました。

Rails 2.0からは with_scopeは protectedメソッドになっていて、外部からはそのままでは呼べなくなったんですね。
コントローラのフィルタを使う scoped_accessというプラグイン(舞波さん製)を使うのが主流なのかな?

scoped_access
http://wota.jp/svn/rails/plugins/branches/stable/scoped_access
http://wota.jp/ac/?date=20060105

どうも、複数モデルにまたがってスコープかけるという話はなさそうで、コントローラのフィルタにしてしまうのもピンとこない。

やりたいことはこんなカンジ。

  • 複数モデルにまたがって with_scopeしたい。
  • モデル外(コントローラとか)からスコープを指定したい。
  • モデル内で sessionは見たくない。
  • スコープ範囲のブロックを細かく指定したい。(旧バージョンの AR#with_scopeを直接呼ぶイメージ)
というわけで、以下のようなクラスを作ってみました。
中身は scoped_accessを参考にしてます。

たとえば、こんなカンジで使うことを想定。
複数モデルに ローカライズを行う例です。

すでにある方法でうまくできるのかもしれないんだけど。。A^^;