Addition to the page rendered when the app throws an exception

I don’t know the official way to request a feature in RoR. I hope this post is reasonably complete and acceptable.

Below is a somewhat trivial diff to actionpack based upon the 7.0.4 version. I would not consider this fully functional yet but I think it is enough to demonstrate the concepts. The concept is essentially stolen from rails-footnotes:

When an exception is thrown, a page is rendered and part of the page has the paths and line numbers from the exception stack. The lines are clickable and when clicked, the upper section changes to show more context of the line in the original source code. This is already existing.

The addition is to add a link symbol after the current link to represent that clicking it will take you out of the page. Currently I have a unicode character whose glyph is two links of a chain which isn’t what I was looking for but it gets the point across. I was looking for the usual arrow pointing to the northeast. I suppose an icon could be used as well.

When the chain character is clicked, the href is a piece of Ruby code that first checks (at render time, not at the time of the click) to see if ext_editor is defined and if it is, it is called passing the “frame”. Otherwise, int_editor is called.

Both my examples of int_editor and ext_editor are just proof of concept. The internal creates a URL using the “file” scheme while the ext_editor creates a URL using the “emacs” scheme.

What might actually be better is for the int_editor to just pop up some help text explaining how to enable the ext_editor or perhaps it could be a static URL to a page with help text on how to define the ext_editor method. The other possibility is to not show the chain link character at all if ext_editor is not defined. But then, how would users find out about the feature?

I thought this approach would be preferred to overriding a method in the code base with another method by the same name in the user’s application.

Another piece of work to do would be to add something like the sample I have to the templates so that config/initializers/debug_view.rb would be created when the Rails app is created.

Having both links, the currently existing link that shows the code snippets and the new link that opens the file in the external editor, gives the users the best of both worlds. They can view in the browser what happened and then click to get them placed in their favorite editor at the line number for the issue.

The key here is “their favorite editor” can be customized to their liking via the ext_editor method.

diff -cr gems/actionpack-7.0.4/lib/action_dispatch/middleware/debug_view.rb gems-new/actionpack-7.0.4/lib/action_dispatch/middleware/debug_view.rb
*** gems/actionpack-7.0.4/lib/action_dispatch/middleware/debug_view.rb	2022-10-18 17:58:32.000000000 -0500
--- gems-new/actionpack-7.0.4/lib/action_dispatch/middleware/debug_view.rb	2022-10-17 21:41:23.000000000 -0500
*** 62,66 ****
--- 62,70 ----
      rescue ActionController::BadRequest
+     def int_editor(frame)
+       frame[:trace].sub(/([^:]+):([0-9]+)(:.*)?/, "file:///Users/pedz/Source/hatred/\\1#\\2")
+     end

diff -cr gems/actionpack-7.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb gems-new/actionpack-7.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
*** gems/actionpack-7.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb	2022-10-18 17:58:32.000000000 -0500
--- gems-new/actionpack-7.0.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb	2022-10-17 21:37:58.000000000 -0500
*** 19,24 ****
--- 19,25 ----
            <a class="trace-frames trace-frames-<%= error_index %>" data-exception-object-id="<%= frame[:exception_object_id] %>" data-frame-id="<%= frame[:id] %>" href="#">
              <%= frame[:trace] %>
+           <a href="<%= respond_to?(:ext_editor) ? ext_editor(frame) : int_editor(frame) -%>">&#128279;</a>
          <% end %>

module ActionDispatch
  class DebugView < ActionView::Base # :nodoc:
    # def ext_editor(frame)
    #   frame[:trace].sub(/([^:]+):([0-9]+)(:.*)?/, "emacs:///Users/pedz/Source/hatred/\\1#\\2")
    # end