Class: MetaRuby::GUI::ExceptionRendering
- Inherits:
-
Object
- Object
- MetaRuby::GUI::ExceptionRendering
- Defined in:
- lib/metaruby/gui/exception_rendering.rb
Overview
Functionality to render exceptions in an HTML view
On top of properly formatting the exception, it introduces backtrace filtering and javascript-based buttons to enable backtraces on or off.
It is usually not used directly, but through HTML::Page
Defined Under Namespace
Classes: BacktraceParser
Constant Summary collapse
- RESSOURCES_DIR =
The directory relative to which ressources (such as css or javascript files) are resolved by default
File.('html', File.dirname(__FILE__))
- HEADER =
Necessary header content
<<-EOD <link rel="stylesheet" href="file://#{File.join(RESSOURCES_DIR, 'exception_view.css')}" type="text/css" /> <script type="text/javascript" src="file://#{File.join(RESSOURCES_DIR, 'jquery.min.js')}"></script> EOD
- SCRIPTS =
The scripts that are used by the other exception templates
<<-EOD <script type="text/javascript"> $(document).ready(function () { $(".backtrace").hide() $("a.backtrace_toggle_filtered").click(function (event) { var eventId = $(this).attr("id"); $("#backtrace_full_" + eventId).hide(); $("#backtrace_filtered_" + eventId).toggle(); event.preventDefault(); }); $("a.backtrace_toggle_full").click(function (event) { var eventId = $(this).attr("id"); $("#backtrace_full_" + eventId).toggle(); $("#backtrace_filtered_" + eventId).hide(); event.preventDefault(); }); }); </script> EOD
- EXCEPTION_TEMPLATE_WITHOUT_BACKTRACE =
Template used to render an exception that does not have backtrace
<<-EOF <div class="message" id="<%= id %>"><pre><%= message.join("\n") %></pre></div> EOF
- EXCEPTION_TEMPLATE_WITH_BACKTRACE =
Template used to render an exception that does have a backtrace
<<-EOF <div class="message" id="<%= id %>"> <pre><%= message.join("\n") %></pre> <span class="backtrace_links"> (show: <a class="backtrace_toggle_filtered" id="<%= id %>">filtered backtrace</a>, <a class=\"backtrace_toggle_full\" id="<%= id %>">full backtrace</a>) </span> </div> <div class="backtrace_summary"> from <%= origin_file %>:<%= origin_line %>:in <%= HTML.escape_html(origin_method.to_s) %> </div> <div class="backtrace" id="backtrace_filtered_<%= id %>"> <%= render_backtrace(filtered_backtrace) %> </div> <div class="backtrace" id="backtrace_full_<%= id %>"> <%= render_backtrace(full_backtrace) %> </div> EOF
- @@exception_id =
0
Instance Attribute Summary collapse
-
#linker ⇒ #link_to
readonly
An object that allows to render a link to an object.
-
#user_file_filter ⇒ #[]
An object that can be used to determine whether a file is a user or framework file.
Class Method Summary collapse
-
.parse_backtrace(backtrace) ⇒ Array<(String,Integer,String)>
Parse a backtrace into its file, line and method consistuents.
Instance Method Summary collapse
-
#allocate_exception_id ⇒ Object
Automatically generate an exception ID.
-
#each_exception_from(e) {|exception| ... } ⇒ Object
Method used by #render to discover all exception objects that are linked to another exception, in cases where exceptions cause one another.
-
#filter_backtrace(parsed_backtrace, raw_backtrace) ⇒ Object
Filters the backtrace to remove framework parts that are not relevant.
-
#head ⇒ Object
Contents necessary in the <head> …
-
#initialize(linker) ⇒ ExceptionRendering
constructor
Create an exception rendering object using the given linker object.
-
#parse_and_filter_backtrace(backtrace) ⇒ (Array<(String,Integer,String)>,Array<(String,Integer,String))> the full and filtered backtraces, as list of tuples (file,line,method)
private
Parses the exception backtrace, and generate a parsed raw and parsed filtered version of it.
-
#render(e, reason = nil, id = allocate_exception_id) ⇒ String
Render an exception into HTML.
-
#render_backtrace(backtrace) ⇒ Object
private
Render a backtrace.
-
#render_single_exception(e, id) ⇒ String
private
Render a single exception object into a HTML block.
-
#scripts ⇒ Object
Scripts block to be added to the HTML document.
-
#user_file?(file) ⇒ Boolean
Return true if the given file is a user file or a framework file.
Constructor Details
#initialize(linker) ⇒ ExceptionRendering
Create an exception rendering object using the given linker object
36 37 38 39 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 36 def initialize(linker) @linker = linker self.user_file_filter = nil end |
Instance Attribute Details
#linker ⇒ #link_to (readonly)
Returns an object that allows to render a link to an object.
19 20 21 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 19 def linker @linker end |
#user_file_filter ⇒ #[]
Returns an object that can be used to determine whether a file is a user or framework file. It is used in backtrace filtering and rendering. The default returns true for any file.
24 25 26 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 24 def user_file_filter @user_file_filter end |
Class Method Details
.parse_backtrace(backtrace) ⇒ Array<(String,Integer,String)>
Parse a backtrace into its file, line and method consistuents
87 88 89 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 87 def self.parse_backtrace(backtrace) BacktraceParser.new(backtrace).parse end |
Instance Method Details
#allocate_exception_id ⇒ Object
Automatically generate an exception ID
176 177 178 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 176 def allocate_exception_id @@exception_id += 1 end |
#each_exception_from(e) {|exception| ... } ⇒ Object
Method used by #render to discover all exception objects that are linked to another exception, in cases where exceptions cause one another
The default implementation only yields ‘e’, reimplement in subclasses
211 212 213 214 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 211 def each_exception_from(e) return enum_for(__method__) if !block_given? yield(e) end |
#filter_backtrace(parsed_backtrace, raw_backtrace) ⇒ Object
Filters the backtrace to remove framework parts that are not relevant
156 157 158 159 160 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 156 def filter_backtrace(parsed_backtrace, raw_backtrace) head = parsed_backtrace.take_while { |file, _| !user_file?(file) } tail = parsed_backtrace[head.size..-1].find_all { |file, _| user_file?(file) } head + tail end |
#head ⇒ Object
Contents necessary in the <head> … </head> section
It is used when enabling the renderer on a [Page] by calling HTML::Page#add_to_setup
72 73 74 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 72 def head HEADER end |
#parse_and_filter_backtrace(backtrace) ⇒ (Array<(String,Integer,String)>,Array<(String,Integer,String))> the full and filtered backtraces, as list of tuples (file,line,method)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parses the exception backtrace, and generate a parsed raw and parsed filtered version of it
224 225 226 227 228 229 230 231 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 224 def parse_and_filter_backtrace(backtrace) full_backtrace = ExceptionRendering.parse_backtrace(backtrace) filtered_backtrace = filter_backtrace(full_backtrace, backtrace) if filtered_backtrace.first.respond_to?(:to_str) filtered_backtrace = ExceptionRendering.parse_backtrace(filtered_backtrace) end return full_backtrace, filtered_backtrace end |
#render(e, reason = nil, id = allocate_exception_id) ⇒ String
Render an exception into HTML
190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 190 def render(e, reason = nil, id = allocate_exception_id) counter = 0 html = [] seen = Set.new each_exception_from(e) do |exception| if !seen.include?(exception) seen << exception html << render_single_exception(exception, "#{id}-#{counter += 1}") end end html.join("\n") end |
#render_backtrace(backtrace) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Render a backtrace
It uses #linker to generate links, and #user_file? to change the style of the backtrace line.
266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 266 def render_backtrace(backtrace) result = [] backtrace.each do |file, line, method| file_link = linker.link_to(Pathname.new(file), file, lineno: line) if user_file?(file) result << " <span class=\"user_file\">#{file_link}:#{line}:in #{HTML.escape_html(method.to_s)}</span><br/>" else result << " #{file_link}:#{line}:in #{HTML.escape_html(method.to_s)}<br/>" end end result.join("\n") end |
#render_single_exception(e, id) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Render a single exception object into a HTML block
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 240 def render_single_exception(e, id) = PP.pp(e, "").split("\n"). map { |line| HTML.escape_html(line) } full_backtrace, filtered_backtrace = parse_and_filter_backtrace(e.backtrace || Array.new) if !full_backtrace.empty? origin_file, origin_line, origin_method = filtered_backtrace.find { |file, _| user_file?(file) } || filtered_backtrace.first || full_backtrace.first origin_file = linker.link_to(Pathname.new(origin_file), origin_file, lineno: origin_line) ERB.new(EXCEPTION_TEMPLATE_WITH_BACKTRACE).result(binding) else ERB.new(EXCEPTION_TEMPLATE_WITHOUT_BACKTRACE).result(binding) end end |
#scripts ⇒ Object
Scripts block to be added to the HTML document
It is used when enabling the renderer on a [Page] by calling HTML::Page#add_to_setup
80 81 82 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 80 def scripts SCRIPTS end |
#user_file?(file) ⇒ Boolean
Return true if the given file is a user file or a framework file
An object used to determine this can be set with #user_file_filter=
This is used by #render_backtrace to choose the style of a backtrace line
169 170 171 |
# File 'lib/metaruby/gui/exception_rendering.rb', line 169 def user_file?(file) user_file_filter[file] end |