Rails6 ログインしているユーザとしていないユーザでアクセスできるページに制限をつけよう！

# 目的

- ログインしているユーザとしていないユーザでアクセスできるページを分ける方法をまとめる

# すいません

- 忘れないうちに記載したくて内容がとても雑です。申し訳ないです。。。

# 実施方法概要

1. ログイン時に`session[:user_id]`にユーザIDを格納
1. アクセスページの制限

# 実施方法詳細

1. ログイン時に`session[:user_id]`にユーザIDを格納
    1. ユーザがログインシーケンスを実行するビューファイルの内容を下記に記載する。(付録のlogin_form.html.erbに記載)

        ```erb
        <%= form_tag("/login") do %>
          <p>メールアドレス</p>
          <input type="text" name="email" value="<%= @enail %>">
          <p>パスワード</p>
          <input type="password" name="password">
          <input type="submit" value="ログイン">
        <% end %>
        ```

    1. 前述のログインシーケンスの値を受け取るコントローラのアクションの内容を下記に記載する。（付録のusers_controller.rbに記載）

        ```rb
        def login
          @user = User.find_by(email: params[:email], password: params[:password])
          if @user
            #ここでsession[:user_id]にユーザIDを格納している。
            session[:user_id] = @user.id
            redirect_to("/posts/index")
          else
            @email = params[:email]
            render("users/login_form")
          end
        end
        ```

    1. ヘッダーに表示されているページリンクの表示/非表示をログインの有無によって設定する。ヘッダーのビューファイルの内容を下記に記載する。(付録のapplication.html.erbに記載。)

        ```erb
        <ul>
          <% if session[:user_id] %>
                #ログインしていてsession[:user_id]にユーザIDが入っている時の表示
          	<li><%= link_to("Home", "/") %></li>
          	<li><%= link_to("このサービスについて", "/about") %></li>
          	<li><%= link_to("つみかさね一覧", "/posts/index") %></li>
          	<li><%= link_to("つみかさね新規登録", "/posts/new") %></li>
          	<li><%= link_to("ユーザ一覧", "/users/index") %></li>
          	<li><%= link_to("ログアウト", "/logout") %></li>
          	<li><%= link_to("#{@current_user.name}", "/users/#{@current_user.id}") %></li>
          <% else %>
                #ログインしておらずsession[:user_id]にユーザIDが入っていない時の表示	
          	<li><%= link_to("Home", "/") %></li>
          	<li><%= link_to("このサービスについて", "/about") %></li>
          	<li><%= link_to("新規登録", "/signup") %></li>
          	<li><%= link_to("ログイン", "/login") %></li>
          <% end %>
        </ul>
        ```     

1. アクセスページの制限
    1. 下記に`session[:user_id]`の値を用いたアクセスページの制限する処理とメソッド定義を記載する。(付録のapplication_controller.rbに記載。application_controller.rbは必ず実行されるため)

        ```rb
        # set_current_userのメソッドを最初に実行する宣言
        before_action :set_current_user
    
        def set_current_user
            #session[:user_id]に格納されているIDを元にユーザデータを格納            
            @current_user = User.find_by(id: session[:user_id])            
        end
    
        # ログインしていない時にページのアクセス制限をつける分岐(判断材料は@current_userがnilかどうか)
        def authenticate_user
            if @current_user == nil
                #flash[:notice] = "ログインが必要です。"
                redirect_to("/login")
            end
        end
    
        # ログインしている時にページのアクセス制限をつける分岐(判断材料は@current_userがnilかどうか)
        def forbid_login_user
            if @current_user != nil
                #flash[:notice] = "すでにログインしています"
                redirect_to("/posts/index")
            end
        end
        ```

    1. ログインしていない時にアクセス制限をかけるページのアクション名を設定する。(本記載はアクセス制限をかけたいページを司るコントローラファイルに記載する。)(付録のusers_controller.rbに記載)

        ```rb
        before_action :authenticate_user, {only: [:アクション名1, :アクション名2, :アクション名3, :アクション名4]}
        ```

    1. ログインしている時にアクセス制限をかけるページのアクション名を設定する。(本記載はアクセス制限をかけたいページを司るコントローラファイルに記載する。)(付録のusers_controller.rbに記載)

        ```rb
        before_action :forbid_login_user, {only: [:アクション名1, :アクション名2, :アクション名3, :アクション名4]}
        ```

# 付録

- 今回の一連の内容に関係するファイルを下記に記載する。

- login_form.html.erb

    ```erb
    <%= form_tag("/login") do %>
        <%= @error_message %>
        <p>メールアドレス</p>
        <input type="text" name="email" value="<%= @enail %>">
        <p>パスワード</p>
        <input type="password" name="password">
        <input type="submit" value="ログイン">
    <% end %>
    ```

- users_controller.rb

    ```rb
    class UsersController < ApplicationController
    
      # :index, :show, :edit, :updateのアクションアクセス時@current_userがnilならはじく
      before_action :authenticate_user, {only: [:index, :show, :edit, :update]}
      before_action :forbid_login_user, {only: [:login_form, :login, :new, :create]}
    
      def index
        @user = User.all
      end
      
      def show
        @user = User.find_by(id: params[:id])
      end
    
      def new
        @user = User.new
      end
    
      def create
        @user = User.new(name: params[:name], email: params[:email], password: params[:password])
        if @user.save
          # flash[:notice] = "登録完了"
          session[:user_id] = @user.id
          redirect_to("/users/#{@user.id}")
        else
          # flash[:notice] = "登録失敗"
          render ("users/new")
        end
      end
    
      def edit
        @user = User.find_by(id: params[:id])
      end
    
      def update
        @user = User.find_by(id: params[:id])
        @user.name = params[:name]
        @user.email = params[:email]
        if @user.save
          # flash[:notice] = "更新完了"
          redirect_to("/users/#{@user.id}")
        else
          # flash[:notice] = "更新失敗"
          render("users/edit")
        end
      end
    
      def login_form
    
      end
    
      def login
        @user = User.find_by(email: params[:email], password: params[:password])
        if @user
          #flash[:notice] = "ログインしました"
          session[:user_id] = @user.id
          redirect_to("/posts/index")
        else
          @error_message = "メールアドレスかパスワードが間違っています。"
          @email = params[:email]
          render("users/login_form")
        end
      end
    
      def logout
        session.delete(:user_id)
        #flash[:notice] = "ログアウトしました"
        redirect_to("/login")
      end
    end
    ```

- application.html.erb

    ```erb
    <!DOCTYPE html>
    <html>
      <head>
        <title>EveyDayStudy</title>
        <%= csrf_meta_tags %>
        <%= csp_meta_tag %>
    
        <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
      </head>
    
      <body>
        <!-- header -->
        <header>
          <nav class="navbar navbar-expand-md navbar-light bg-light sticky-top">
          	<div class="container-fluid">
          	  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive">
          	  	<span class="navbar-toggler-icon"></span>
          	  </button>
          	  <div class="collapse navbar-collapse" id="navbarResponsive">
          	    <ul class="navbar-nav ml-auto">
    		      <% if session[:user_id] %>
    		      	<li class="navbar-item"><%= link_to("Home", "/", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("このサービスについて", "/about", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("つみかさね一覧", "/posts/index", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("つみかさね新規登録", "/posts/new", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("ユーザ一覧", "/users/index", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("ログアウト", "/logout", {method: "delete", class: "nav-link"}) %></li>
        	      	<li class="navbar-item"><%= link_to("#{@current_user.name}", "/users/#{@current_user.id}", {class: "nav-link"}) %></li>
    		      <% else %>	
    		      	<li class="navbar-item"><%= link_to("Home", "/", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("このサービスについて", "/about", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("新規登録", "/signup", {class: "nav-link"}) %></li>
    		      	<li class="navbar-item"><%= link_to("ログイン", "/login", {class: "nav-link"}) %></li>
    		      <% end %>
          	    </ul>
          	  </div>
          	</div>
          </nav>
        </header>
    	<!--header end-->
    
        <!-- main -->
        <main>
          <%= yield %>
        </main>
    	<!-- main end -->
    
    	<!-- footer -->
        <footer>
    	    <div class="container-fluid padding">
    	    	<div class="row text-center">
    	    		<div class="col-md-4">
    	    			<hr class="light">
    	    			<p>000-0000-0000</p>
    	    			<p>email@mail.com</p>
    	    			<p>miriwo</p>
    	    			<p>City, Statem, 0000</p>
    	    		</div>
    	    		<div class="col-md-4">
    	    			<hr class="light">
    	    			<h5>Our hours</h5>
    	    			<hr class="light">
    	    			<p>Monday: 9:00~17:00</p>
    	    			<p>Saturaday: 10:00~16:00</p>
    	    			<p>Sunday: close</p>
    	    		</div>
    	    		<div class="col-md-4">
    	    			<hr class="light">
    	    			<h5>service Area</h5>
    	    			<hr class="light">
    	    			<p>City, Statem, 0000</p>
    	    			<p>City, Statem, 0000</p>
    	    			<p>City, Statem, 0000</p>
    	    		</div>
    	    		<div class="col-12">
    	    			<hr class="light-100">
    	    			<h5>&copy; miriwo.com</h5>
    	    		</div>
    	    	</div>
    	    </div>
        </footer>
        <!-- footer end -->
    
      </body>
    </html>
    ```

- application_controller.rb

    ```rb
    class ApplicationController < ActionController::Base
        before_action :set_current_user                            
        def set_current_user            
            @current_user = User.find_by(id: session[:user_id])            
        end
    
        def authenticate_user
            if @current_user == nil
                #flash[:notice] = "ログインが必要です。"
                redirect_to("/login")
            end
        end
    
        def forbid_login_user
            if @current_user != nil
                #flash[:notice] = "すでにログインしています"
                redirect_to("/posts/index")
            end
        end
    end
    ```