chroju.dev/blog

the world as code

RoRでログイン機能を実装する

  • sessionに情報を保存することで「ログイン」状態を実現する
  • 逆に言えばsession破棄で「ログアウト」扱いになる
  • Railsにはsessionオブジェクトが用意されており、これを使えば簡単にsessionへアクセス可能

……というわけで。

1. sessionコントローラを作成する

$ rails g controller sessions new create destroy
  • コントローラ作成のときは複数形!
  • newはログイン画面表示時に、createはログイン処理時に、destroyはログアウト処理時に使用

コントローラを作成したらとりまログイン処理を書いていく

  <span class="synPreProc">def</span> <span class="synIdentifier">create</span>↲
      user = <span class="synType">User</span>.find_by_name(params[<span class="synConstant">:name</span>])↲
      <span class="synStatement">if</span> user <span class="synStatement">and</span> user.authenticate(params[<span class="synConstant">:password</span>])↲
          session[<span class="synConstant">:user_id</span>] = user.id↲
          redirect_to tasks_url↲
      <span class="synStatement">else</span>↲
          redirect_to login_url, <span class="synConstant">:alert</span> => <span class="synSpecial">"</span><span class="synConstant">無効なユーザー名/パスワードです。</span><span class="synSpecial">"</span>↲
      <span class="synStatement">end</span>↲
  <span class="synPreProc">end</span>↲

  • フォームで入力した値など、URLパラメータを受け取るときはparamsを使う
  • authenticateメソッドは、引数とuserのパスワードダイジェストを比較して論理値を返す
  • タスク管理アプリを作っているので、ログイン成功時のリダイレクト先はtasks_url
  • ちな、hoge_urlは絶対パス、hoge_pathは相対パスになるらしい
  • 302 Redirectでは完全修飾URLに飛ぶのが仕様なので、redirect_toではhoge_urlを使う
  • 失敗時はlogin_urlに返し、エラーメッセージを渡す

2. ログイン画面を作成する

/app/views/sessions/new.html.erbを編集

 <span class="synIdentifier"><</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"form"</span><span class="synIdentifier">></span>↲
    <span class="synIdentifier"><% if flash[:alert] %></span>↲
        <span class="synIdentifier"><</span><span class="synStatement">p</span><span class="synIdentifier"> </span><span class="synType">id</span><span class="synIdentifier">=</span><span class="synConstant">"notice"</span><span class="synIdentifier">><%=</span><span class="synConstant"> flash[:alert]</span><span class="synIdentifier"> %></</span><span class="synStatement">p</span><span class="synIdentifier">></span>↲
    <span class="synIdentifier"><% end %></span>↲
↲
    <span class="synIdentifier"><%=</span><span class="synConstant"> form_tag</span><span class="synIdentifier"> do %></span>↲
        <span class="synIdentifier"><</span><span class="synStatement">fieldset</span><span class="synIdentifier">></span>↲
            <span class="synIdentifier"><</span><span class="synStatement">legend</span><span class="synIdentifier">></span>ログインして下さい<span class="synIdentifier"></</span><span class="synStatement">legend</span><span class="synIdentifier">></span>↲
↲
            <span class="synIdentifier"><</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
                <span class="synIdentifier"><%=</span><span class="synConstant"> label_tag</span><span class="synIdentifier"> :</span><span class="synType">name</span><span class="synIdentifier">, </span><span class="synConstant">'ユーザー名:'</span><span class="synIdentifier"> %></span>↲
                <span class="synIdentifier"><%=</span><span class="synConstant"> text_field_tag</span><span class="synIdentifier"> :</span><span class="synType">name</span><span class="synIdentifier">, params[:</span><span class="synType">name</span><span class="synIdentifier">] %></span>↲
            <span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
↲
            <span class="synIdentifier"><</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
                <span class="synIdentifier"><%=</span><span class="synConstant"> label_tag</span><span class="synIdentifier"> :password, </span><span class="synConstant">'パスワード:'</span><span class="synIdentifier"> %></span>↲
                <span class="synIdentifier"><%=</span><span class="synConstant"> password_field_tag</span><span class="synIdentifier"> :password, params[:password] %></span>↲
            <span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
↲
            <span class="synIdentifier"><</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
                <span class="synIdentifier"><%=</span><span class="synConstant"> submit_tag</span><span class="synIdentifier"> </span><span class="synConstant">"ログイン"</span><span class="synIdentifier"> %></span>↲
            <span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲
        <span class="synIdentifier"></</span><span class="synStatement">fieldset</span><span class="synIdentifier">></span>↲
    <span class="synIdentifier"><% end %></span>↲
<span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span>↲

  • 冒頭部分はログイン失敗時のalertメッセージ表示部分

  • flashオブジェクトについて良くわかってないので要調査

  • hoge_tagあたりのヘルパーメソッドももうちょっと調べときたい

3. ルーティング

config/routes.rbを編集してlogin周りのルーティングを設定する。以下の5行を追加。

controller sessions <span class="synStatement">do</span>
    get <span class="synSpecial">'</span><span class="synConstant">login</span><span class="synSpecial">'</span> => <span class="synConstant">:new</span>
    post <span class="synSpecial">'</span><span class="synConstant">login</span><span class="synSpecial">'</span> => <span class="synConstant">:create</span>
    delete <span class="synSpecial">'</span><span class="synConstant">logout</span><span class="synSpecial">'</span> => <span class="synConstant">:destroy</span>
<span class="synStatement">end</span>

  • sessionsコントローラに対し、

  • /loginにGETでアクセスした場合はsessions#newを呼ぶ

  • /loginにPOSTでアクセスした場合はsessions#createを呼ぶ

  • /logoutにDELETEでアクセスした場合はsessions#destroyを呼ぶ

  • すなわちREST

ざっくり簡単だが、とりあえずこれで認証画面とログイン処理は実装完了。

まだログアウトはできていないし、ログイン後の処理なんかも書いてないけど、とりあえずやりかたはわかったのでメモ。

参考

Ruby on Rails ログイン画面の作成 - ayaketanのプログラミング勉強日記