例外処理

アクションには、例外処理のための洗練されたAPIがあります。この動作は、現在の花見環境とカスタム設定で変更されます。

 

デフォルト動作

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action

    def call(params)
      raise 'boom'
    end
  end
end

プロダクションモードでは例外が自動的にキャッチされますが、開発時には例外になりません。実例では、この例では、アプリケーションは500(Internal Server Error)を返します。開発時には、スタックトレースとコードをデバッグするためのすべての情報が表示されます。

この動作は、のhandle_exceptions設定で変更できapps/web/application.rbます。

 

カスタムHTTPステータス

特定のHTTPステータスコードに例外をマップする場合は、handle_exceptionDSL を使用できます。

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    handle_exception ArgumentError => 400

    def call(params)
      raise ArgumentError
    end
  end
end

handle_exceptionキーが処理する例外であるハッシュを受け取り、値は対応するHTTPステータスコードです。この例では、いつArgumentError呼び出されますか400(Bad Request)として処理されます。

 

カスタムハンドラ

カスタムHTTPステータスを持つマッピングが私たちのニーズに合っていない場合、カスタムハンドラを指定して、自分で例外を管理できます。

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class PermissionDenied < StandardError
    def initialize(role)
      super "You must be admin, but you are: #{ role }"
    end
  end

  class Index
    include Web::Action
    handle_exception PermissionDenied => :handle_permission_error

    def call(params)
      unless current_user.admin?
        raise PermissionDenied.new(current_user.role)
      end

      # ...
    end

    private
    def handle_permission_error(exception)
      status 403, exception.message
    end
  end
end

値としてメソッドの名前(シンボルとして)を指定したhandle_exception場合、このメソッドは例外に応答するために使用されます。上記の例では、不要なアクセスからアクションを保護したいと考えています。管理者だけが許可されています。

PermissionDenied例外が発生すると、例外が処理され:handle_permission_errorます。exception引数を受け入れなければなりません(内部で呼び出された例外インスタンス)#call

カスタム例外ハンドラを指定するときは、exception引数を受け入れなければなりません。