RAILS PRESS RUBY on RAILS, it’s DRY and COOL …

RSS Feed

RAILS PRESS RSS

Tag Cloud

はてなブックマーク - railspress.matake.jp の注目エントリー
象形文字くさび形文字ミイラそろばんの玉そろばんコーラン占いの板?象牙大英博物館
« 前のエントリ
Ruby on Railsの使えるレンタルサーバ
次のエントリー »
OpenIDでプロフィール情報を受け取る際のフォーマット(openid.sreg.*)

Posted on
2008/02/08

Tags
Gem, OpenID, Plugin, Rails2.0, トラップ, バグ

Keywords


この記事をはてなブックマークに登録 この記事のはてなブックマーク数 この記事を livedoor クリップに登録この記事の livedoor クリップ数 このエントリを del.icio.us に追加
ブックマークに追加する

OpenId Authentication Pluginのサンプルにはまった。

最近RailsのOpenIdAuthentication Pluginに挑戦しています。

open_id_authenticationプラグインの導入はこちらを参考にしました。

open_id_authentication*[認証][Rails] open_id_authenticationをつかってみる - KazusaAPI開発日誌 - KDRIグループ

koress.jp: 解消法: open_id_authenticationプラグイン(rails 2.0.2)

サンプルを動かしてみてOpenID Profider(IdP)からリダイレクトされてくるところまではスムーズに行ったのですが、その後のレスポンスを解析する部分で、このプラグインに添付してあるサンプルソースに潜んだバグ(?)にはまりました。

具体的にハマったのは、サンプルソース内の以下の部分で使われているcase .. when構文の比較ルール。

LANG : RUBY
  1. authenticate_with_open_id do |result, identity_url|
  2.   case result
  3.   when :missing
  4.     failed_login "Sorry, the OpenID server couldn't be found"
  5.   when :canceled
  6.     failed_login "OpenID verification was canceled"
  7.   when :failed
  8.     failed_login "Sorry, the OpenID verification failed"
  9.   when :successful
  10.     if @current_user = @account.users.find_by_identity_url(identity_url)
  11.       successful_login
  12.     else
  13.       failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
  14.     end
  15.   end
  16. end

ここでは以下のような評価を想定されているようです。

LANG : RUBY
  1. status === :missing

ちなみにこの「===(code)」メソッドは

LANG : shell etc.
  1. RAILS_ROOT/vendor/plugins/open_id_authentication/lib/open_id_authentication.rb

にて、内部クラスResultに定義されています。
(参考:/plugins/open_id_authentication/lib/open_id_authentication.rb - Rails Trac - Trac

しかしcase .. when構文で実行される比較命令は

LANG : RUBY
  1. whenの引数)=== (caseの引数)

となるようで、実行されるのは以下の比較命令になります。

LANG : RUBY
  1. :missing === status

この場合、Symbolクラスのオブジェクトである「:missing」とResultクラスのオブジェクトである「Result[:missing]」が、Symbolクラスに定義された「===(var)」メソッドで比較されるので、当然「false」になります。

Plugin作者的には、Resultクラスの「===(code)」メソッドでResult内部の「@code」と引数のシンボルを比較することを想定しているのだと思いますが、実際にはここでは全ての比較がSymbolクラスの「===(var)」で行われ、結果としてどのwhen句も実行されることはありません。

ここが全く分からずに、本当にはまりました...

LANG : shell etc.
  1. A===B

LANG : shell etc.
  1. B===A

が違うなんて...Rubyは(僕には?)まだまだ奥深い。

結局最終的には

LANG : shell etc.
  1. RAILS_ROOT/vendor/plugins/open_id_authentication/lib/open_id_authentication.rb

のResultクラス内に

LANG : RUBY
  1. def code
  2.   @code
  3. end

というメソッドを追加して、先ほどのcaseの引数をresultではなくresult.codeとすることで、以下のコードは期待通りに動作するようになりました。

LANG : RUBY
  1. authenticate_with_open_id do |result, identity_url|
  2.   case result.code
  3.   when :missing
  4.     failed_login "Sorry, the OpenID server couldn't be found"
  5.   when :canceled
  6.     failed_login "OpenID verification was canceled"
  7.   when :failed
  8.     failed_login "Sorry, the OpenID verification failed"
  9.   when :successful
  10.     if @current_user = @account.users.find_by_identity_url(identity_url)
  11.       successful_login
  12.     else
  13.       failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
  14.     end
  15.   end
  16. end

やれやれ、まさかこんなところではまるとは...

このプラグイン、作者DHHらしいんですが、「===(code)」をどうやって使うつもりだったんだろう??

僕の使い方が間違っているのかなぁ〜??


この記事がお役に立ちましたら、一言コメントもらえると嬉しいですm_ _m

[...] ただし「OpenId Authentication Pluginのサンプルにはまった。 » RAILS PRESS」で紹介したバグはまだなおっていませんでした。そういえばここにはsatokoさんもはまっていたようです。 [...]


Posted by
technohippy
2009/04/2 3pm

DHHのことだからパッチ当てたSymbolクラス使ってるんですよ、きっと


Posted by
NOV
2009/04/2 4pm

あぁ、なるほど、そういうことか。


コメントはこちらから




使用可能タグ: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


« 前のエントリ
Ruby on Railsの使えるレンタルサーバ
次のエントリー »
OpenIDでプロフィール情報を受け取る際のフォーマット(openid.sreg.*)