在rescue_from块中请求.format

ami*_*hle 6 ruby-on-rails

我有一个带有rescue_from块的轨道控制器,我可以在其中调用render.

class SomeController < ApplicationController
  rescue_from Some::Error, :some_error

  private

  def some_error error
    @error = error
    render 'error'
  end
end
Run Code Online (Sandbox Code Playgroud)

奇怪的是,即使我有一个error.js.erb视图,rails也会一直使用error.html.erb,即使请求是JS:

Started GET /some/1
Processing by SomeController#show as JS
...
Rendered some/error.html.erb
Run Code Online (Sandbox Code Playgroud)

不是如何在它上面的缩短日志中表示它呈现为JS,但它仍然使用HTML文件.该.js.erb是在正确的位置,并呈现JS的看法时,有没有rescue_from涉及的作品就好了.

这里发生了什么?

更新1:我已经创建了一个测试存储库来演示该问题

更新2 我找到了解决方案(见下文).任何人都可以提出一个更通用的解决方案,如下面的那些,或者你能告诉我为什么这将是不可能的或一个非常糟糕的主意?赏金仍然开放.

  • 难道是有意义的创建一个拉请求设置self.formatsActionController::Rescue.process_action
  • 变得非常疯狂并尝试将错误的堆栈恢复到比错误引发的位置更深的位置

ami*_*hle 5

我在rails源代码中做了一些调试和挖掘,并自己找到了一个解决方案:

def error
  @error = error
  self.formats = request.formats.map(&:ref).compact
  render 'error'
end
Run Code Online (Sandbox Code Playgroud)

说明

调用rescue_from块发生在ActionController::Rescue.process_action.如果有错误,将调用该块.如果没有错误,最终ActionController::Rendering.process_action会调用刚刚设置的self.formats:

def process_action(*) #:nodoc:
  self.formats = request.formats.map(&:ref).compact
  super
end
Run Code Online (Sandbox Code Playgroud)

这是一个完整的堆栈跟踪ActionController::Rescue.process_action和实际的控制器操作.

#0  TestController.index at /tmp/rescue_from/app/controllers/test_controller.rb:11
#1  ActionController::ImplicitRender.send_action(method#String, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/implicit_render.rb:4
#2  AbstractController::Base.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/abstract_controller/base.rb:198
#3  ActionController::Rendering.process_action(action, *args) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/rendering.rb:10
#4  block in AbstractController::Callbacks.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/abstract_controller/callbacks.rb:20
?-- #5  Proc.call(*args) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115
#6  ActiveSupport::Callbacks::Filters::End.call(env#ActiveSupport::Callbacks::Filters::Environment) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115
#7  block (2 levels) in ActiveSupport::Callbacks::CallbackChain.compile at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:553
?-- #8  Proc.call(*args) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503
#9  ActiveSupport::Callbacks::CallbackSequence.call(*args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503
#10 ActiveSupport::Callbacks.run_callbacks(kind#Symbol, &block#Proc) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88
#11 AbstractController::Callbacks.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/abstract_controller/callbacks.rb:19
#12 ActionController::Rescue.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/rescue.rb:29
Run Code Online (Sandbox Code Playgroud)

当出现错误时(抛出a before_action),这是一个完整的堆栈跟踪:

--> #0  TestController.standard_error(error#RuntimeError) at /Users/timou/tmp/rescue_from/app/controllers/test_controller.rb:20
?-- #1  Method.call(*args) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/rescuable.rb:80
#2  ActiveSupport::Rescuable.rescue_with_handler(exception#RuntimeError) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.3/lib/active_support/rescuable.rb:80
#3  ActionController::Rescue.rescue_with_handler(exception#RuntimeError) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/rescue.rb:15
#4  rescue in ActionController::Rescue.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/rescue.rb:32
#5  ActionController::Rescue.process_action(action#NilClass, *args#Array) at /usr/local/Cellar/rbenv/0.4.0/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/rescue.rb:29
Run Code Online (Sandbox Code Playgroud)

所以我的问题实际上是错误是在a中引发的before_action,这是由设置AbstractController::Callbacks.process_action之前处理和发生的.ActionController::Rendering.process_actionself.formats

如果错误的行动本身提出,self.formats将已经被设置和正确政绩观将不设置被渲染self.formatsrescue_from块.