before_actionを特定の場所に効かせるために

初めに

  • application_controllerで以下のものを定義して、ログインしていないユーザーに対してアクセス制限をかけるようにした。
def authenticate_user
   if @current_user == nil
     flash[:notice] = "ログインが必要です"
     redirect_to("/login")
   end
 end
  • 今回はposts_controllerの全てのアクション、users_controllerのindex,show,update,editアクションのみに制限をかけたい

問題

  • アクセス制限をかけたくないhomes_controllerのtop,aboutアクションにもアクセス制限がかかっていた。

コード

application_controller
class ApplicationController < ActionController::Base
before_action :set_current_user
before_action:authenticate_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
end
posts_controller
class PostsController < ApplicationController
  before_action :authenticate_user
                
  def index
    @posts = Post.all.order(created_at: :desc)
  end
  
  def show
    @post = Post.find_by(id: params[:id])
  end
  
  def new
    @post = Post.new
  end
  
  def create
    @post = Post.new(content: params[:content])
    if @post.save
      flash[:notice] = "投稿を作成しました"
      redirect_to("/posts/index")
    else
      render("posts/new")
    end
  end
  
  def edit
    @post = Post.find_by(id: params[:id])
  end
  
  def update
    @post = Post.find_by(id: params[:id])
    @post.content = params[:content]
    if @post.save
      flash[:notice] = "投稿を編集しました"
      redirect_to("/posts/index")
    else
      render("posts/edit")
    end
  end
  
  def destroy
    @post = Post.find_by(id: params[:id])
    @post.destroy
    flash[:notice] = "投稿を削除しました"
    redirect_to("/posts/index")
  end
  
end
users_controller
class UsersController < ApplicationController
  before_action :authenticate_user ,{only:[:index,:show,:edit,:update]}
  
  def index
    @users = 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],
      image_name:"default_user.jpg",
      password: params[:password]
      )
    if @user.save
     
      session[:user_id] = @user.id
      flash[:notice] = "ユーザー登録が完了しました"
      redirect_to("/users/#{@user.id}")
    else
      @email = params[:email]
      @password = params[:password]
      @name = params[:name]
      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 params[:image]
    @user.image_name = "#{@user.id}.jpg"
    image = params[:image]
    File.binwrite("public/user_images/#{@user.image_name}",image.read)
   end
    if @user.save
      flash[:notice] = "ユーザー情報を編集しました"
      redirect_to("/users/#{@user.id}")
    else
      render("users/edit")
    end
  end
  def login_form
  end
  
  def login
    @user = User.find_by(password: params[:password], email: params[:email])
    if @user
     session[:user_id] = @user.id
     flash[:notice] = "ログインしました"
     redirect_to("/posts/index")
    else
      @email = params[:email]
      @password = params[:password]
      @error_message = "メールアドレスまたはパスワードが間違っています"
     render("users/login_form")
    end
  end
  def logout
      session[:user_id] = nil
      flash[:notice] = "ログアウトしました"
      redirect_to("/login")
    
  end
  
end
home_controller
class HomeController < ApplicationController
  def top
    
  end
  
  def about
    
  end
end

原因

  • application_controllerでbefore_action:authenticate_userを定義しているために全てのcontrollerにアクセス制限をかけてしまっていた。

  • application_controllerでbefore_action:authenticate_userを削除してアクセス制限をかけたいcontrollerでbefore_action:authenticateを定義する。

結語

  • application_controllerでbefore_actionを定義してしまうと全てのcontrollerに影響を与えてしまう

  • application_controllerで定義したメソッドは他のcontrollerで利用できるので 今回はアクセス制限をかけたいcontroller内でbefore_actionを定義しなくてはいけない。