概要
サインアップしたユーザーが、メールアドレスとパスワードでサインインし、サインアウトする機能を実装する。
セッションによるアクセス制限などの管理は後に実装し、ここではユーザー認証とページ遷移だけにとどめる。
サインイン機能
サインイン処理アクション
サインインが要求されたとき、sign_in
アクションからサインインのビューがレンダリングされる。ビューのフォームとの間でUser
モデルを介してデータをやりとりするので、アクションでUser
モデルのインスタンスを生成しておく。
1 2 3 4 5 6 7 8 9 10 11 12 |
class UsersController < ApplicationController ..... def sign_in @user = User.new render layout: 'application_signed_out' end ..... end |
フォームでのモデルの設定
サインインのビュー、sign_in.html.erb
のform_with
ヘルパーで、コントローラーで生成されたUser
モデルのインスタンスを指定する。
app/views/users/sign_in.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="sign_in_page"> <h1>EX-BBS</h1> <div class="sign_in_form"> <h2>サインインページ</h2> <%= form_with model: @user, url: sign_in_path, local: true do |f| %> <%= f.email_field :email, placeholder: "メールアドレスを入力" %> <%= f.password_field :password, placeholder: "パスワードを入力" %> <button>サインイン</button> <p>ユーザー登録したい方は<%= link_to "サインアップへ", sign_up_path %></p> <% end %> </div> </div> |
サインイン処理
サインインフォームの入力情報は、users_controller
のsign_in_process
アクションにPOSTされる(ルーティングは「フォームの入力を確認する」で設定した)。
users_controller
に、以下のsign_in_process
メソッドを追加する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class UsersController < ApplicationController def sign_up ..... def sign_in ..... def sign_in_process @user = User.new(user_params) encrypted_password = User.generate_digest(user_params[:password]) user = User.find_by(email: user_params[:email], password: encrypted_password) if user redirect_to top_path and return else flash.now[:danger] = "サインインできません" render :sign_in, layout: 'application_signed_out' and return end end private def user_params ..... end |
処理の流れは以下のとおり。
- POSTされたデータを
user_params
メソッドにより受け取る(user_params
についてはform_with
とモデルの使い方を参照) user_params
を使って入力データがセットされたUser
インスタンスを生成- ユーザー登録時と同じ方法で暗号化されたパスワード(ダイジェスト)を生成
- メールアドレスとパスワードダイジェストで、データベースからユーザーを検索
- ユーザーが存在する場合、サインインとして
top
ページにリダイレクト - ユーザーが存在しない場合、エラーメッセージをセットして再度サインイン画面をレンダリング(
@user
に入力データがセットされているので、サインイン画面にメールアドレスが残る)
サインアウト機能
サインインに成功すると、トップ画面に遷移する。
トップ画面を始めサインイン後にアクセス可能な画面は全てヘッダーメニューを持つ。そのメニュー中、サインアウトの項目をサインイン画面へのリンクとする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!DOCTYPE html> <html> ..... <body> <header> <div class="header_logo"></div> <h1>EX-BBS</h1> <ul class="header_menu"> <li><%= link_to("投稿する", "#") %></li> <li><%= link_to("プロフィール", "#") %></li> <li><%= link_to("サインアウト", sign_in_path) %></li> </ul> </header> <%= yield %> </body> </html> |