AR삽질러

Rails 一日一つメソッド (Day10) before_actionメソッド 본문

Ruby/RubyOnRails-日本語

Rails 一日一つメソッド (Day10) before_actionメソッド

아랑팡팡 2023. 12. 30. 18:15
728x90

オプション

Rails 一日一つメソッド (Day10) before_actionメソッド

 

before_actionメソッド

 - Controllerのアクションが実行される前に特定の処理を実行するためにフィルダーとしてbefore_actionが用意されている。

例)ログインしてないユーザがアクセスできないページを実装する場あい、before_actionを使用してログイン状態を確認する処理を実行できる。

 

before_actionメソッド使用方法

 - Controllerは複数のアクションを実行できるが、その一部のアクションにのみbefore_actionを適用したい場合はonlyオプションを使用する。

 

before_actionを使用するには、コントローラー直下で以下のように記述する。

before_action :method名
class UserController < ApplicationController
	# ユーザ認証
	before_action :authenticate_user, only: [:edit, :update, :destroy]
    
    # 権限確認
    before_action :correct_user, only: [:edit, :update, :destroy]
    
    # session管理
    before_action :redirect_if_logged_in_only: [:newm, :create]
end

 

Controller内でメソッドを定義し、before_actionの引数では、メソッド名のシンボルを指定する。

 

before_actionのオプション

オプション 意味
:only before_actionを適用したアクションを指定
:except before_actionを適用しないアクションを指定
:if before_actionを適用する条件に指定
:unless before_actionを適用しない条件に指定

 


:onlyオプション

Controllerのactionの中で一部のアクションにのみ適用したい場合はonlyオプションを指定する。

edit, update アクションにのみauthenticate_userメソッドが実行される。

class UserController < ApplicationController
	before_action :authenticate_user, only: [:edit, :update]
    
    def edit
    	@user = User.find(params[:id])
    end
    
    def update
    	@user = User.find(params[:id])
        if @user.update(user_params)
        	redirect_to @user
        else
        	render :edit
        end
    end
    
    private
    	def authenticate_user
        	unless user_signed_in?
            	redirect_to new_user_session_path
            end
        end
        
        def user_params
        	params.require(:user).permit(:name, :email)
        end
end

 


:exceptオプション

onlyオプションの逆で、特定のアクションにはフィルターを適用しないようにする。

indexアクションとshowアクションにはauthenticate_userメソッドを実行しない。

class UsersContrller < ApplicationController
	before_action :authenticate_user, except: ["index, :show]
    
    def index
    	@users = User.all
    end
    
    def show
    	@user = User.find(params[:id])
    end
    
    private
    	def authenticate_user
        	unless user_signed_in?
           		redirect_to new_user_session_path 
            end
        end
end

 


:ifオプション

条件を指定して特定のアクションにのみフィルターを実行する。

editアクションにのみauthenticate_userメソッドが実行される。

class UsersController < ApplicationController
  before_action :authenticate_user, if: -> { params[:action] == 'edit' }

  def index
    @users = User.all
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to @user
    else
      render :edit
    end
  end

  private

  def authenticate_user
    unless user_signed_in?
      redirect_to new_user_session_path
    end
  end

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

 


:unlessオプション

ifオプションの逆で、適用しない条件を指定する。

indexアクション以外のアクションに対して、authenticate_userメソッドが実行される。

class UsersController < ApplicationController
	before_action :authenticate_user, unless: -> { params[:action] == 'index' }

	def index
    	@user = User.all
    end
    
    def show
    	@user = User.find(params[:id])
    end

	private
    	def authenticate_user
        	unless user_signed_id?
            	redirect_to new_user_session_path
            end
        end
end

 


UserController.rb

class UsersController < ApplicationController

    before_action :correct_user, only: [:user_show, :edit, :update, :destroy]

    def user_show
        @user = User.find_by(id: params[:id])
        redirect_to users_path, alert: 'ユーザーが見つかりませんでした。' if @user.nil?
    end  
    
    # new -> save로 변경하기
    def create
        @user = User.create(user_param)
      
        if @user.persisted?
          redirect_to user_path(@user), notice: 'ユーザーが登録されました。'
        else
          render :new
        end
    end      
       
    def destroy
        @user = User.find(params[:id])
        @user.destroy
        redirect_to users_path, notice: 'ユーザーが削除されました。'
    end

    def edit
        @user = User.find(params[:id])
    end

    def update
        @user = User.find(params[:id])
        if @user.update(user_param)
          redirect_to users_path, notice: 'ユーザーがupdateされました。'
        else
          render :edit, status: :unprocessable_entity
        end
    end      

    private
        def correct_user
            @user = User.find_by(id: params[:id])
            unless @user && @user == current_user
              flash[:alert] = 'ユーザー情報に接近できません。。Loginしてください!'
              redirect_to root_path
            end
        end
end

 

before_action :correct_user, only: [:user_show, :edit, :update, :destroy]

 - currect_userメソッドはuser_show, update, destroy アクションが実装される前に呼び出され、先に実行される。Loginしたユーザーが自分の情報にのみ接近できるようにする。

 

@user = User.find_by(id: params[:id])
 - URLでidパラメータを使用して、該当するユーザーをデータベースから見つけ、@user変数に割り当てる。
unless @user && @user == current_user
 - 現在ログインしているユーザー(current_user)が@user変数に割り当てられたユーザーと同一であることを確認する。
つまり、ログインしたユーザーが他のユーザーの詳細情報ページにアクセスしようとしたり、他のユーザーの情報を修正、更新、削除しようとする試みを防止するための条件。
flash[:alert] = 'ユーザー情報に接近できません。。Loginしてください!'
 ユーザーが他のユーザーの情報にアクセスしようとする場合、警告メッセージをflash[:alert]に設定。
redirect_to root_path
 アラート メッセージの設定後は、ユーザーをルート パス(通常はホームページ)にリダイレクト。

 

home.html.erb

<h1>Pages#home</h1>
<p>Find me in app/views/pages/home.html.erb</p>

<% flash.each do |key, value| %>
    <div class="flash <%= key %>"><%= value %></div>
<% end %><br>

<%= link_to '会員登録', signup_path %><br><br>

<%= link_to 'ユーザList', users_path %><br><br>

<%= link_to 'Login', login_path %>

 

 


 

https://github.com/designAR/rails_method_study/tree/day10_before_action

 

GitHub - designAR/rails_method_study

Contribute to designAR/rails_method_study development by creating an account on GitHub.

github.com

 

728x90
반응형
LIST