Controllerに記述された同様の処理の省略(Ruby on Rails)

以下のように記述されたコントローラーのコードを可読性を向上させるために、before_actionを用いて省略します。

※一例なのでアクションやコードは一部省略しています。

app/controllers/items_controller.rb
class ItemsController < ApplicationController
  def index
    @items = Item.all.order('created_at DESC')
  end

  def show
    @item = Item.find(params[:id])
  end

  def edit
    @item = Item.find(params[:id])
    unless @item.user.id == current_user.id
      redirect_to action: :index
    end
  end

  def update
    @item = Item.find(params[:id])
    @item.update
  end
end

上記のコードを見てみると、@item = Item.find(params[:id])という記述が随所に見られます。このように記述しても動作には問題ありませんが、コードの可読性を上げたい場合、これを効率良く記述したいです。そのためにはbefore_actionを用います。
 before_actionは、コントローラーで定義されたアクションが実行される前にbefore_actionに定義した処理を全て共通のものとして実行することができます。さらにonlyやexceptといったオプションを付与することで、指定したアクションに対してbefore_actionを実行することができます。それでは、before_actionを用いてまとめたコードを見てみましょう。

※一例なのでアクションやコードは一部省略しています。

app/controllers/items_controller.rb
class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :edit, :update]
  before_action :user_match, only: [:edit, :update]
 
  def index
    @items = Item.all.order('created_at DESC')
  end

  def show
  end
 
  def edit
  end
 
  def update
    @item.update
  end

  private

  def set_item
    @item = Item.find(params[:id])
  end
 
  def user_match
    unless @item.user.id == current_user.id
      redirect_to action: :index
    end
  end
end

上記のコードの、before_actionの記述の見方は以下の通りです。

before_action :処理を行いたいメソッドの名前, only: [:限定するアクションの名前]

そして、private以下に一つの共通する処理として書き出してまとめています。このようにコードを省略することにより読みやすくなりました。
 またuser_matchメソッドに対してeditアクション以外にupdateアクションを指定し、before_actionの処理としてまとめている理由としては第三者がリクエストを改ざんし、editアクションの編集ページを経由しないでupdateアクションを動かすことができる可能性があるからです。deviseによるユーザー管理機能をアプリケーションに実装しているのであれば、セキュリティ対策として以下のようなeditアクションに記述された条件分岐のコードをupdateアクションにも付け加える必要があります。

unless @item.user.id == current_user.id
  redirect_to action: :index
end

そのためbefore_actionのメソッドとしてまとめています。

この記事が気に入ったらサポートをしてみませんか?