モデル名やメソッド名はサンプル通りが無難

Deviseを使ってみたら「user_signed_in?」とか「current_user」とかの基本的なヘルパーメソッドが全然動いている様子がないので、またあれこれググってしまった。どうもRails3リリースへ向けて動いていたころには、ヘルパーを定義する初期化ファイルの呼び出し順序の問題で、そういう現象が起こっていたらしく、いろいろとMLの議論やブログが出てくる。

しかし、どうにも動かない。30分ほども悩んだ挙句、はっと気づいたのは、「current_user」というメソッド名は動的に生成されているもので、正確には「current_」とモデル名が埋め込まれてるってことなのだ。気付いてみれば、そりゃそうかと思ったけど、ぼくはUserモデルはプロフィールなんかを入れるもの使うことにして、それとは別にdevise用にAccountモデルを作ったのだった。なので、ヘルパーメソッドは「current_account」となる。

こういう辺りもRails初心者にありがちな失敗ってことなんだろうな。ドキュメントに書いてあるメソッド名は、あくまでも個別ケース。

で、認証用アカウントと、ユーザーアカウントを別モデルとして扱うべきなのかどうかというそもそも論的なところも、やっぱり議論があって、「よほどの理由がない限り、User一発でやっちまえよ」ということだった。deviseのコントローラやモデルのカスタマイズ方法が良く分からないし、あまりテーブルが大きくなるのって良くないのかと思って、いっそ別にしようと思ったけど、これは間違いだったらしい。deviseの挙動を変えるのは、単にオーバーライドすればいいだけらしい。例えば、認証にemailだけでなく、usernameも併用する(どちらでもログインできる)ようにするには、

def self.find_for_database_authentication(conditions)
  value = conditions[authentication_keys.first]
  where(["username = :value OR email = :value", { :value => value }]).first
end

というのをモデルに書いて、モデルクラスのクラスメソッドをオーバーライドすればいい。

特別な理由がない限り、ドキュメント通り、デフォルト、良く使われている名前を使えというのはCoCの精神とも言えて、例えば、Deviseのような認証プラグインを使ったはいいけど、コントローラやビューにアクションの許可・不許可や表示の有無のコードが分散してしまう、という問題を解決するプラグインの「CanCan」は、標準では「current_user」というメソッドの存在を前提としているらしい。カスタマイズは可能だけど、やっぱりこういうところも考えると、モデル名はUserにしておくのが、あちこち修正しなくて済む幸せへの道なのだろう。

当たり前だけど、サンプル以上のことをやろうとすると、いろいろと調べたり、ちゃんと理解したりということが必要になってきて、想像したより難しいなぁと思うけど、結局そうやって一歩ずつ進んでいくことがフレームワークを使うってことなんだろうなと考えを改めつつある。

CanCanって、すごいな。

can [:update, :destory], [Article, Comment]

とか宣言しておけば、ArticleやCommentの更新、破棄には認証が必要となるように挙動を変更できる。そっか、CanCanって、フレンチカンカンではなくて、「You can update it and can destroy that!」というようなニュアンスの命名だったのか。

CanCanみたいなのが出てくるってのがRailsの進化を象徴している気がする。