deviseのafter_sign_in_path_forをHashで華麗に書く

Hash Selector Patternという記事を読んでいたら、コメントにdeviseのafter_sign_in_path_forをHashで華麗に書いてあるコードがあって、「おおっ」と思ったのでした。というわけで今日はRubyの話。

こんなコード

ユーザーのタイプに応じてログイン後のページを変える場合、大体こんな感じのif分岐になると思います(もしくはcase文とか)。

def after_sign_in_path_for(resource)
  if resource.kind_of?(AdminUser)
    admin_dashboard_path
  elsif resource.kind_of?(Customer)
    customer_root_path
  elsif resource.kind_of?(Staff)
    staff_root_path
  elsif resource.kind_of?(Agent)
    agent_root_path
  end
end

でもHashを使うとこんな感じに書ける。

SIGN_IN_PATHS = { staff:      -> { staff_root_path },
                  agent:      -> { agent_root_path },
                  admin_user: -> { admin_dashboard_path },
                  customer:   -> { customer_root_path } }

def after_sign_in_path_for(resource)
  SIGN_IN_PATHS[resource.class.name.underscore.to_sym].call
end

HashのキーにProcクラスのオブジェクトを入れると、多少宣言的に書ける。lambda記法も相まって、ちょっとCoffeeScriptっぽいですよね。

JavaScriptで書いているときは、実は当たり前のように書いているコードなのだけど、Rubyになるとこういう発想がなかった。やはり言語は思考を既定するのだなーと、改めて思ったのでした。