我有一个带rescue_from
块的rails控制器,我在其中调用render
。
class SomeController < ApplicationController
rescue_from Some::Error, :some_error
private
def some_error error
@error = error
render 'error'
end
end
奇怪的是,即使我有error.js.erb
视图,rails也会始终使用error.html.erb
,即使请求是JS
:
Started GET /some/1
Processing by SomeController#show as JS
...
Rendered some/error.html.erb
上面的缩短日志中没有说它如何呈现为JS,但它仍然使用HTML文件。 .js.erb
位于正确的位置,并且当没有rescue_from
涉及的工作正常时,呈现JS视图。
这里发生了什么?
更新1 :我创建了test repository来演示问题
更新2 我找到了解决方案(见下文)。任何人都可以提出一个更通用的解决方案,如下面的那些,或者你能告诉我为什么这将是不可能的或一个非常糟糕的主意?赏金仍然开放。
self.formats
或 ActionController::Rescue.process_action
是否有意义
答案 0 :(得分:5)
<强>解决方案强>
我在rails源代码中进行了一些调试和挖掘,并自己找到了解决方案:
def error
@error = error
self.formats = request.formats.map(&:ref).compact
render 'error'
end
<强>解释强>
在ActionController::Rescue.process_action
中调用rescue_from
阻止。如果有错误,将调用该块。如果没有错误,最终会调用ActionController::Rendering.process_action
来设置self.formats
:
def process_action(*) #:nodoc:
self.formats = request.formats.map(&:ref).compact
super
end
这是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
当出现错误(在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
所以我的问题实际上是before_action
引发的错误,由AbstractController::Callbacks.process_action
处理并在ActionController::Rendering.process_action
设置self.formats
之前发生。
如果操作本身出现错误,则已设置self.formats
,并且在self.formats
块中没有设置rescue_from
的情况下呈现正确的视图。