CodeZine(コードジン)

特集ページ一覧

Rails 5でログインフォームを実装する

サンプルコードで学ぶRuby on Rails 5実践入門 第5回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/03/17 14:00
目次

Sessionsコントローラーと対応するルーティング・ビューの作成

 ログイン/ログアウトを制御するための最もメジャーな方法はセッションを使うことです。セッションは、サーバーとクライアント(サーバーにアクセスする端末のブラウザ等)の接続を担保します。セッション管理のためにSessionsコントローラーを作成しましょう。

$ bin/rails g controller Sessions new

 実行コマンドの末尾の「new」はnewアクションのみ、という意味です。ログインに必要なビューはnewアクションに対応するものだけで良いため、newを指定しています。ただ、このままではルーティングにnewアクションしか定義されません。実際はログインに対応するcreateアクション、ログアウトに対応するdestroyアクションも必要となるのでルーティングを追加しましょう。

リスト6 config/routes.rb
Rails.application.routes.draw do
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
…(中略)…

 なお、newアクションのルーティングも/loginでアクセスできるように修正しています。

 newアクションに対応するビューファイルを作成します。

リスト7 app/views/sessions/new.html.erb
…(中略)…
	<%= form_for(:session, url: login_path) do |f| %>
      <div class="field">
        <%= f.label :email %>
        <%= f.email_field :email %>
      </div>
      <div class="field">
        <%= f.label :password %>
        <%= f.password_field :password %>
      </div>
      <div class="actions">
        <%= f.submit "Log in" %>
      </div>
    <% end %>
    <p>New user? <%= link_to "Sign up now!", new_user_path %></p>
…(中略)…

 Usersコントローラーのnewアクションに対応するフォームのビューファイルである、app/views/users/_form.html.erbと似ていますが、form_forの引数に違いがあることが分かるでしょう。form_forメソッドは、Usersリソースのように対応するコントローラーとモデルが一致している場合は第2引数を省略できますが、Sessionsリソースでは対応するモデルがないため、第2引数に対応するURLを指定する必要があります。ここではlogin_pathが指定されているため、ルーティングで対応するSessionsコントローラーのcreateメソッド内でparams[:session]とすることにより、フォームの情報を取得することができます。

ログインの実装

 それではログイン機能をSessionsコントローラーに実装していきましょう。現状はジェネレーターコマンドで作成したSessionsコントローラーに、空のnewメソッドが追加されているだけです。これに、ログインに対応するcreateメソッドの実装を行っていきます。

リスト8 app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
…(中略)…
  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      reset_session
      session[:user_id] = user.id
      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end
…(中略)…

 先ほど解説した通り、フォームで入力されたemailはparams[:session][:email]で取得することができます。後に続くdowncaseはRubyのメソッドで、大文字を全て小文字に変換します。メールアドレスは大文字と小文字の区別がないので、フォームで大文字が入力された場合にも、小文字でusersテーブルからユーザーレコードを検索できるようにする必要があります。そのためdowncaseしています。

 次のif文では該当するuserが見つかり、なおかつフォームで入力されたパスワードでログインが成功した場合にのみ、直下にあるブロックの処理が実行されます。そうでない場合、else以下の処理に続くようになっています。authenticateはhas_secure_passwordメソッドを追加すると自動的に利用できるようになるメソッドで、引数にパスワードを指定することでログインが成功したか否かを返却します。

 ログインが成功した場合、Railsが提供するreset_sessionメソッドでセッションを初期化した後、session変数にユーザーIDを格納し、次の行で該当ユーザーの詳細画面にリダイレクトしています。

[解説]ルーティングの省略形

 「redirect_to user」の「user」はちょっと不思議に感じるかもしれません。このコードは「redirect_to user_url(user)」と同じ意味です。これなら分かるのではないでしょうか。そう、「/users/[ユーザーID]」ですね。

 userはUserモデルインスタンスなので、対応するルーティングをRailsが類推してくれているのです。

 引き続きelse文以下を見てみましょう。flash.now[:danger]のflashとは、Railsが提供するメッセージングの仕組みで、簡単なメッセージを画面に表示することができます。flash.nowとすることにより現在のアクションでビューがレンダリングされた場合にのみ、設定されたメッセージを表示してくれます。後に続く[:danger]はflashメッセージの種類を定義しています。ここではログインに失敗したことを、ユーザーに気付いてもらうべき致命的なエラーとして通知するためにdangerとしています。

 しかし、このままではエラーメッセージが表示されません。ビューファイルに対して、flashメッセージが設定された場合に表示するブロックを記述する必要があります。flashメッセージはビュー共通で出力したいので、ここでは共通のビューテンプレートであるlayoutsを用いて記述します。

リスト9 app/views/layouts/application.html.erb
…(中略)…
  <body>
    <% flash.each do |message_type, message| %>
      <div class="alert alert-<%= message_type %>"><%= message %></div>
    <% end %>
    <%= yield %>
  </body>
…(中略)…

 ソースコードのようにflashオブジェクトをeachでループすることで、message_typeごとに設定されたメッセージを表示することができます。先の例ではmessage_type=dangerのメッセージが「Invalid email/password combination」となります。

 また、該当メッセージのdivのclassにmessage_typeに応じたclassを設定しています。先の例ではalert-dangerクラスが付与されます。

 それでは実際に/loginにアクセスしてみましょう。

図1 http://localhost:3000/login
図1 http://localhost:3000/login

 あらかじめユーザー登録しておいたユーザーで、まずはパスワードを空にしたままでログインを試みます。先ほど指定した、メールアドレスとパスワードが無効であるエラーメッセージが表示されることを確認できると思います。

図2 http://localhost:3000/login
図2 http://localhost:3000/login

 今度は正しいパスワードでログインを試みてみましょう。ログインが成功するとログインユーザーの詳細ページ(本稿では/users/1)にリダイレクトするはずです。

図3 http://localhost:3000/users/1
図3 http://localhost:3000/users/1

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:サンプルコードで学ぶRuby on Rails 5実践入門

もっと読む

著者プロフィール

  • WINGSプロジェクト 竹馬 力(チクバ ツトム)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5