これから作っていく簡単なWebアプリの作成メモ(自分の備忘)です。
自分用なのであまり凝りすぎないように書いていきたい。
今回やったこと
今回はユーザーがログインできるようにしたい。
以下の記事で詳細な説明をしていたのでぜひ紹介したい。
【Rails】ログイン機能を実装する
上記の記事を大いに参考にさせていただきます。
bcryptは導入済み、User.rbにもhash_secure_passwordを追加済みなので、セッションを利用したユーザー管理ができるようにする。
Sessionsコントローラーを作成する。
$ rails g controller Sessions new
ルーティングを作成しておく。
(略)
# Sessions
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
(略)
各種の処理と画面を作成する。
まずは画面寄りの部分。
$ touch ./app/views/sessions.new.html.erb
<h1>ログイン</h1>
<%= form_for(:session, url: login_path) do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>
  <%= f.label :password %>
  <%= f.password_field :password %>
  <%= f.submit "Log in" %>
<% end %>
(略)
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
  <% if logged_in? %>
    <a class="dropdown-item" href="<%= root_path %>">ホーム</a>
    <a class="dropdown-item" href="<%= schedules_path %>">予定</a>
    <a class="dropdown-item" href="<%= users_path %>">ユーザー</a>
    <a class="dropdown-item" href="<%= logout_path %>" data-method="delete">ログアウト</a>
  <% else %>
    <a class="dropdown-item" href="<%= login_path %>">ログイン</a>
  <% end %>
</div>
(略)
※aタグでdeleteのリクエストを送信するためにdata-method属性を設定しているが、以下の記事を参考にした。
[Rails]aタグでも「data-method="delete"」を設定すればlink_toと同じ挙動
link_toで突然methodが効かなくなって困ってるあなたへ
次に内部処理寄りの部分。
まずはヘルパーから。
module SessionsHelper
 # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
  end
  # 現在ログイン中のユーザーを返す (いる場合)
  def current_user
    if session[:user_id]
      #@current_user = @current_user || User.find_by(id: session[:user_id])と同じ意味
      @current_user ||= User.find_by(id: session[:user_id])
    end
  end
  #受け取ったユーザーがログイン中のユーザーと一致すればtrueを返す
  def current_user?(user)
    user == current_user
  end
  # ユーザーがログインしていればtrue、その他ならfalseを返す
  def logged_in?
    !current_user.nil?
  end
  # 現在のユーザーをログアウトする
  def log_out
    session.delete(:user_id)
    @current_user = nil
  end
end
次にコントローラーの処理。
class ApplicationController < ActionController::Base
  include SessionsHelper
end
class SessionsController < ApplicationController
  def new
  end
  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      redirect_to root_url
    else
      render 'new'
    end
  end
  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
end
また、ログインしていないユーザーをログインページにリダイレクトするアクションを作成。
class ApplicationController < ActionController::Base
  include SessionsHelper
  private
   # ログイン済みユーザーかどうか確認
    def logged_in_user
      unless logged_in?
        redirect_to login_url
      end
    end
end
logged_in_userをスケジュールとユーザーのコントローラーのbefore処理として記述。
class SchedulesController < ApplicationController
  before_action :logged_in_user
(略)
class UsersController < ApplicationController
  before_action :logged_in_user
(略)
以上で参考記事をもとにしたログイン処理の追加が完了した。
あとは、ログイン画面がプロトなので(以下添付画像のような見た目)、

これを以下のように手を加えた。
<h1>ログイン</h1>
<%= form_for(:session, url: login_path, html: {class: "form-signin"}) do |f| %>
  <div class="form-label-group my-3">
    <%= f.label :email %>
    <%= f.email_field :email, class: "form-control", placeholder: "Eメールアドレス" %>
  </div>
  <div class="form-label-group my-3">
    <%= f.label :password %>
    <%= f.password_field :password, class: "form-control", placeholder: "パスワード" %>
  </div>
  <div class="d-grid gap-2">
    <%= f.submit "ログイン", class: "btn btn-lg btn-primary my-3" %>
  </div>
<% end %>
こうすると、以下のようにログイン画面が表示される。
結構進んだ。
まだログイン失敗時も含め、方々のエラーメッセージ表示ができないが、今回はここまで。

