Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何从Rails 4中的ActionDispatch::ParamSpaser::ParseError中解救_Ruby On Rails_Ruby_Exception_Params_Rescue - Fatal编程技术网

Ruby on rails 如何从Rails 4中的ActionDispatch::ParamSpaser::ParseError中解救

Ruby on rails 如何从Rails 4中的ActionDispatch::ParamSpaser::ParseError中解救,ruby-on-rails,ruby,exception,params,rescue,Ruby On Rails,Ruby,Exception,Params,Rescue,Rails 4添加了一个异常ActionDispatch::ParamsParser::ParseError异常,但由于它位于中间件堆栈中,因此它似乎无法在正常的控制器环境中被解救。在json API应用程序中,我希望使用标准错误格式进行响应 这显示了插入中间件以拦截和响应的策略。按照这种模式,我有: application.rb: module Traphos class Application < Rails::Application .... config.mid

Rails 4添加了一个异常ActionDispatch::ParamsParser::ParseError异常,但由于它位于中间件堆栈中,因此它似乎无法在正常的控制器环境中被解救。在json API应用程序中,我希望使用标准错误格式进行响应

这显示了插入中间件以拦截和响应的策略。按照这种模式,我有:

application.rb:

module Traphos
  class Application < Rails::Application
    ....
    config.middleware.insert_before ActionDispatch::ParamsParser, "JSONParseError"
 end
end
class JSONParseError
  def initialize(app)
    @app = app
  end

  def call(env)
    begin
      @app.call(env)
    rescue ActionDispatch::ParamsParser::ParseError => e
      [422, {}, ['Parse Error']]
    end
  end
end
如果在没有中间件的情况下运行测试(规范):

这正是我所期望的(我无法挽救的错误)

现在,在上面的中间件中添加唯一的更改:

  2) Photo update attributes with non-parseable json
     Failure/Error: response.status.should eql(422)

       expected: 422
            got: 200
日志显示标准控制器操作正在执行并返回正常响应(尽管由于它没有收到任何参数,所以没有更新任何内容)

我的问题是:

  • 如何从ParseError中恢复并返回自定义响应。感觉我在正确的轨道上,但不完全正确

  • 我不明白为什么,当异常被引发和解救时,控制器操作仍然在进行


  • 非常感谢您的帮助,-Kip

    证明,在中间件堆栈的更上层,ActionDispatch::ShowExceptions可以配置一个exceptions应用程序

    module Traphos
      class Application < Rails::Application
        # For the exceptions app
        require "#{config.root}/lib/exceptions/public_exceptions"
        config.exceptions_app = Traphos::PublicExceptions.new(Rails.public_path)
      end
    end
    
    在测试环境中使用它需要设置配置变量(否则在开发和测试中会得到标准的异常处理)。因此,为了测试,我已经(编辑为只包含关键部分):

    它以公共API的方式按照我的需要执行,并适用于我可能选择定制的任何其他例外情况。

    本文(也是从2013年开始)也涵盖了此主题。只有在您请求json时,他们才会将响应放在这个中间件服务中

    if env['HTTP_ACCEPT'] =~ /application\/json/
        error_output = "There was a problem in the JSON you submitted: #{error}"
        return [
          400, { "Content-Type" => "application/json" },
          [ { status: 400, error: error_output }.to_json ]
        ]
    else
     raise error
    end
    

    是否有其他中间件更改退货状态?你有没有用pry做过调试?
    module Traphos
      class PublicExceptions
        attr_accessor :public_path
    
        def initialize(public_path)
          @public_path = public_path
        end
    
        def call(env)
          exception    = env["action_dispatch.exception"]
          status       = code_from_exception(env["PATH_INFO"][1..-1], exception)
          request      = ActionDispatch::Request.new(env)
          content_type = request.formats.first
          body         = {:status => { :code => status, :exception => exception.class.name, :message => exception.message }}
          render(status, content_type, body)
        end
    
        private
    
        def render(status, content_type, body)
          format = content_type && "to_#{content_type.to_sym}"
          if format && body.respond_to?(format)
            render_format(status, content_type, body.public_send(format))
          else
            render_html(status)
          end
        end
    
        def render_format(status, content_type, body)
          [status, {'Content-Type' => "#{content_type}; charset=#{ActionDispatch::Response.default_charset}",
                    'Content-Length' => body.bytesize.to_s}, [body]]
        end
    
        def render_html(status)
          found = false
          path = "#{public_path}/#{status}.#{I18n.locale}.html" if I18n.locale
          path = "#{public_path}/#{status}.html" unless path && (found = File.exist?(path))
    
          if found || File.exist?(path)
            render_format(status, 'text/html', File.read(path))
          else
            [404, { "X-Cascade" => "pass" }, []]
          end
        end
    
        def code_from_exception(status, exception)
          case exception
          when ActionDispatch::ParamsParser::ParseError
            "422"
          else
            status
          end
        end
      end
    end
    
    describe Photo, :type => :api do
      context 'update' do
        it 'attributes with non-parseable json' do 
    
          Rails.application.config.consider_all_requests_local = false
          Rails.application.config.action_dispatch.show_exceptions = true
    
          patch update_url, {:description => description}
          response.status.should eql(422)
          result = JSON.parse(response.body)
          result['status']['exception'].should match(/ParseError/)
    
          Rails.application.config.consider_all_requests_local = true
          Rails.application.config.action_dispatch.show_exceptions = false
        end
      end
    end
    
    if env['HTTP_ACCEPT'] =~ /application\/json/
        error_output = "There was a problem in the JSON you submitted: #{error}"
        return [
          400, { "Content-Type" => "application/json" },
          [ { status: 400, error: error_output }.to_json ]
        ]
    else
     raise error
    end