RubyMine (またはIntelliJ IDEA)で、deviseのヘルパーが認識されない問題を回避する方法

Ruby on Railsでのユーザ認証機能には、定番として devise がよく用いられます。

また、Ruby on Railsでのアプリは、JetBrainsRubyMine (もしくは同機能を包含した IntelliJ IDEA)を用いると非常に効率よく開発を進めることができます。

しかし、この便利なdeviseを用いたRailsプロジェクトを、RubyMineIntelliJ IDEAで編集する場合に、deviseが提供するcurrent_userやuser_signed_in? ((Userクラスをdeviseを用いて作成した場合)) などの便利なヘルパーメソッドを認識してくれないという問題が発生します。

IDEが認識をしていないだけですので、実際にそれらのヘルパーメソッドを用いて作成した機能は正常動作するのですが、それらのヘルパーメソッドを用いる箇所で、IDEによる補完機能の恩恵を受けることが出来なくなります。また、文法違反の可能性があるとして警告が出てしまうため、他の本当に対処すべき問題を埋もれさせてしまう(潜在的なバグを見つけにくくなる)という問題もはらみます。

これは、RubyMineが動的に生成されたメソッドを認識して文法チェックすることが出来ないために発生していると思われます。

そこで、その問題を回避するため、以下のようなヘルパーを app/helpers/application_helper.rb に追記します(この例は、ログイン用にdeviseで作成したモデルのクラスがUserの場合)。

# IDEの補完機能を有効にするため、Deviseのヘルパを宣言
def authenticate_user!(opts={})
  opts[:scope] = :user
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def user_signed_in?
  !!current_user
end

def current_user
  @current_user ||= warden.authenticate(:scope => :user)
end

def user_session
  current_user && warden.session(:user)
end

上記に追加したヘルパーメソッド群、元々のdeviseの中ではより柔軟に様々なモデルに対して適用できるように以下のようなコードがevalで動的に処理されます。(Github上の該当ファイル)

def authenticate_#{mapping}!(opts={})
    opts[:scope] = :#{mapping}
      warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def #{mapping}_signed_in?
  !!current_#{mapping}
end

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
end

def #{mapping}_session
  current_#{mapping} && warden.session(:#{mapping})
end

この #{mapping} の部分は devise 管理下で作成されたモデル名を元にして引数として渡されたものと置き換えられます。たとえば、Userモデルクラスの場合は #{mapping} の部分は user となります。

上記のような、任意のモデル名に対応することが可能なヘルパーメソッド定義となっているものを、特定モデルに特化したヘルパメソッド定義のせいで発生している問題を、特定のモデルに特化したヘルパーメソッドを定義することで回避するという対策です。

同様の方法で動的にメソッドを追加している箇所は他にもあるため、deviseを用いてコーディングをしている時に補完が働かないという現象が発生した場合は、必要に応じて同様の処理を行うと解決させられるかもしれません。

ところで余談ですが、RubyMineやIntelliJ IDEAは、サムライズムさんのような日本の代理店から日本的な商慣行での購入も可能です。開発効率を劇的に向上してくれる非常にパワフルなIDEですので、まずは30日間の無料体験をしてみてはいかがでしょうか。((とはいえ、これを確認に来た方はすでにRubyMineかIntelliJ IDEAユーザさんなのではないかと思いますが。))

なお、Railsでの devise の導入方法や使用方法については日本語のブログでの解説記事も多数ありますので、本エントリでは割愛いたします。