diff --git a/lib/web_console.rb b/lib/web_console.rb index 07250cfb..3f3f88af 100644 --- a/lib/web_console.rb +++ b/lib/web_console.rb @@ -11,6 +11,7 @@ module WebConsole autoload :ExceptionMapper autoload :Session autoload :Injector + autoload :Interceptor autoload :Request autoload :WhinyRequest autoload :Permissions diff --git a/lib/web_console/extensions.rb b/lib/web_console/extensions.rb index 8e54da06..945d6ac4 100644 --- a/lib/web_console/extensions.rb +++ b/lib/web_console/extensions.rb @@ -21,27 +21,3 @@ def console(binding = Bindex.current_bindings.second) nil end end - -module ActionDispatch - class DebugExceptions - def render_exception_with_web_console(request, exception) - render_exception_without_web_console(request, exception).tap do - backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner") - error = ExceptionWrapper.new(backtrace_cleaner, exception).exception - - # Get the original exception if ExceptionWrapper decides to follow it. - Thread.current[:__web_console_exception] = error - - # ActionView::Template::Error bypass ExceptionWrapper original - # exception following. The backtrace in the view is generated from - # reaching out to original_exception in the view. - if error.is_a?(ActionView::Template::Error) - Thread.current[:__web_console_exception] = error.cause - end - end - end - - alias_method :render_exception_without_web_console, :render_exception - alias_method :render_exception, :render_exception_with_web_console - end -end diff --git a/lib/web_console/interceptor.rb b/lib/web_console/interceptor.rb new file mode 100644 index 00000000..c084153c --- /dev/null +++ b/lib/web_console/interceptor.rb @@ -0,0 +1,18 @@ +module WebConsole + module Interceptor + def self.call(request, exception) + backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner") + error = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception).exception + + # Get the original exception if ExceptionWrapper decides to follow it. + Thread.current[:__web_console_exception] = error + + # ActionView::Template::Error bypass ExceptionWrapper original + # exception following. The backtrace in the view is generated from + # reaching out to original_exception in the view. + if error.is_a?(ActionView::Template::Error) + Thread.current[:__web_console_exception] = error.cause + end + end + end +end diff --git a/lib/web_console/railtie.rb b/lib/web_console/railtie.rb index 8797b428..f567533c 100644 --- a/lib/web_console/railtie.rb +++ b/lib/web_console/railtie.rb @@ -10,6 +10,8 @@ class Railtie < ::Rails::Railtie initializer "web_console.initialize" do require "bindex" require "web_console/extensions" + + ActionDispatch::DebugExceptions.register_interceptor(Interceptor) end initializer "web_console.development_only" do diff --git a/test/web_console/extensions_test.rb b/test/web_console/extensions_test.rb deleted file mode 100644 index 2a4ee48b..00000000 --- a/test/web_console/extensions_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -require "test_helper" -require "web_console/extensions" - -module ActionDispatch - class DebugExceptionsTest < ActionDispatch::IntegrationTest - class Application - def call(env) - WebConsole::View.new(ActionView::LookupContext.new([])).render(inline: <<~ERB) - <% @ivar = 42 %> - <%= nil.raise %> - true, - "action_dispatch.show_exceptions" => true, - "action_dispatch.logger" => Logger.new(StringIO.new) - } - - assert_equal 42, Thread.current[:__web_console_exception].bindings.first.eval("@ivar") - end - end -end diff --git a/test/web_console/interceptor_test.rb b/test/web_console/interceptor_test.rb new file mode 100644 index 00000000..0bbf4ab4 --- /dev/null +++ b/test/web_console/interceptor_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "test_helper" + +module WebConsole + class InterceptorTest < ActionDispatch::IntegrationTest + test "follows ActionView::Template::Error original error in Thread.current[:__web_console_exception]" do + request = Request.new({}) + request.set_header("action_dispatch.backtrace_cleaner", ActiveSupport::BacktraceCleaner.new) + + Interceptor.call(request, generate_template_error) + + assert_equal 42, Thread.current[:__web_console_exception].bindings.first.eval("@ivar") + end + + def generate_template_error + WebConsole::View.new(ActionView::LookupContext.new([])).render(inline: <<~ERB) + <% @ivar = 42 %> + <%= nil.raise %> + err + err + end + end +end diff --git a/web-console.gemspec b/web-console.gemspec index 48e4d765..19fb9308 100644 --- a/web-console.gemspec +++ b/web-console.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.4" - rails_version = ">= 5.2" + rails_version = ">= 6.0.0.a" s.add_dependency "railties", rails_version s.add_dependency "activemodel", rails_version