Callbackメソッドの「only」「except」の使い分け(Rails)

【結論】

・Controllerのコールバックメソッドは、onlyexceptで実行するアクションを指定できるが、適切に使い分けないと、バグ発生の要因となり得る

・基本的にonlyを使用する。指定するアクションが増えて、追加するアクションが無くなったらexceptに置き換える。

・権限の制御など、アクションの実行に制限を設けるコールバックであれば、始めからexceptを利用する。

【目次】

【本題】

Callbackメソッドのオプションの使い分け

before_actionafter_actionといったControllerのCallbackメソッドは、オプションでコールバックを実行させるアクションを指定することができます。

onlyでは、指定したアクションだけ、コールバックが実行されます。

exceptでは、指定したアクション以外で、コールバックが実行されます。

class PostsController < ApplicationController
  before_action :authenticate_user!, :except=>[:show]
  before_action :set_post, only: [:show, :edit]

  def show
    @post_comments = PostComment.where(post_id: params[:id])
  end

  def edit
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end
end

これにより、共通の処理を一つの記述にまとめることが出来て、コードの見通しが良くなります。

暗黙的に実行されていることによる弊害

しかしコールバックの処理は、アクション内では明示されていない為、存在を見落としてしまう可能性もあります。

そうなると、アクションを指定し忘れてしまい、それによって意図せぬ挙動が発生してしまうリスクがあります。

例えば、本来は管理者しかアクセスできないページ(アクション)に、一般のユーザーもアクセスできてしまうという事象です。

なので、アクションの指定方法も、それらのリスクを最小限に留めるように設定を行う必要があります。

基本的にonlyを使用する

exceptだと明示的に指定したアクション以外にコールバックが適用されます。

なので、アクションを追加した際にコールバックを見落としてしまうと、本来適用したくなかったコールバックが適用されてしまうことになってしまいます。

onlyを使用すれば、実行するアクションを明示的に指定できるので、意図せぬコールバックが適用される事態は防げます。

しかし、適用するアクションが増えるほど記述量が多くなり、見通しが悪くなることで、どのアクションにコールバックが適用されているのか見辛くなります。

そこで、exceptで書いた方が記述量が減るのであれば、exceptに置き換えましょう。

但し、今後もアクションを追加する予定があるのであれば、exceptに置き換えることで先ほどの問題が発生する可能性もあるので、アクションの追加がひと段落してからの方が良いでしょう。

制限を設けるコールバックはexceptを使用する

基本的にはonlyを使用しますが、exceptを使用した方が良いと思われる場合もあります。

それはコールバックによって、アクションの実行に制限を設ける場合です。

例えば「管理者のみアクセスできるようにしたい」といった権限の制御などです(そもそもコールバックで処理すべきでは無いかもしれないですが・・・)

これをonlyで設定してしまうと、もしコールバックの設定を見逃した場合、一般のユーザーでも管理者専用のアクションが実行できてしまいます。

exceptを使用すれば、追加したアクションに直ぐコールバックが適用されるので、こういった事態を防ぐことが可能です。

参考情報

Action Controller の概要 - Railsガイド

AbstractController::Callbacks::ClassMethods