5

私の Rails 3.2 アプリでは、config.exceptions_app を使用してルーティング テーブルを介して例外をルーティングし、エラー固有のページ (特に 401 Forbidden のページ) をレンダリングしようとしています。設定のためにこれまでに得たものは次のとおりです。

# application.rb
config.action_dispatch.rescue_responses.merge!('Error::Forbidden' => :forbidden)
config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }

# development.rb
config.consider_all_requests_local       = false

# test.rb
config.consider_all_requests_local       = false

そして今、問題の本質:

module Error
  class Forbidden < StandardError
  end
end

class ErrorsController < ApplicationController
  layout 'error'

  def show
    exception       = env['action_dispatch.exception']
    status_code     = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
    rescue_response = ActionDispatch::ExceptionWrapper.rescue_responses[exception.class.name]

    render :action => rescue_response, :status => status_code, :formats => [:html]
  end

  def forbidden
    render :status => :forbidden, :formats => [:html]
  end
end

その 401 応答をレンダリングしたいときは、単純raise Error::Forbiddenに、開発環境で完璧に動作します。ただし、rspec で例を実行する場合は、次のようになります。

it 'should return http forbidden' do
  put :update, :id => 12342343343
  response.should be_forbidden
end

それは惨めに失敗します:

1) UsersController PUT update when attempting to edit another record should return http forbidden
   Failure/Error: put :update, :id => 12342343343
   Error::Forbidden:
     Error::Forbidden

これが私のテスト環境で機能しない理由を誰かが理解するのを手伝ってくれますか? ApplicationControllerに#rescue_from を配置することもできconfig.exceptions_appますが、テストを機能させるためにそれを行う必要がある場合、そもそも使用する意味がわかりません。:-\

編集: 回避策として、config/environments/test.rb の最後に次のコードを追加しました。

module Error
  def self.included(base)
    _not_found = -> do
      render :status => :not_found, :text => 'not found'
    end

    _forbidden = -> do
      render :status => :forbidden, :text => 'forbidden'
    end

    base.class_eval do
      rescue_from 'ActiveRecord::RecordNotFound', :with => _not_found
      rescue_from 'ActionController::UnknownController', :with => _not_found
      rescue_from 'AbstractController::ActionNotFound', :with => _not_found
      rescue_from 'ActionController::RoutingError', :with => _not_found
      rescue_from 'Error::Forbidden', :with => _forbidden
    end
  end
end
4

2 に答える 2

2

セットconfig/environments/test.rb内:

config.action_dispatch.show_exceptions = true
于 2013-10-18T04:10:34.730 に答える