Skip to content

Commit

Permalink
show locals and instance variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Charlie Somerville committed Dec 8, 2012
1 parent 99f3ba8 commit 0cb7986
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 21 deletions.
20 changes: 20 additions & 0 deletions lib/better_errors/core_ext/exception.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Exception
attr_reader :__better_errors_bindings_stack

original_initialize = instance_method(:initialize)

define_method :initialize do |*args|
unless Thread.current[:__better_errors_exception_lock]
Thread.current[:__better_errors_exception_lock] = true
begin
@__better_errors_bindings_stack = []
2.upto(caller.size) do |index|
@__better_errors_bindings_stack << binding.of_caller(index) rescue break
end
ensure
Thread.current[:__better_errors_exception_lock] = false
end
end
original_initialize.bind(self).call(*args)
end
end
17 changes: 14 additions & 3 deletions lib/better_errors/error_frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ class ErrorFrame
def self.from_exception(exception)
exception.backtrace.each_with_index.map { |frame, idx|
next unless frame =~ /\A(.*):(\d*):in `(.*)'\z/
ErrorFrame.new($1, $2.to_i, $3)
ErrorFrame.new($1, $2.to_i, $3, exception.__better_errors_bindings_stack[idx])
}.compact
end

attr_reader :filename, :line, :name
attr_reader :filename, :line, :name, :frame_binding

def initialize(filename, line, name)
def initialize(filename, line, name, frame_binding)
@filename = filename
@line = line
@name = name
@frame_binding = frame_binding
end

def application?
Expand Down Expand Up @@ -53,6 +54,16 @@ def pretty_path
end
end

def local_variables
return {} unless frame_binding
Hash[frame_binding.eval("local_variables").map { |x| [x, frame_binding.eval(x.to_s)] }]
end

def instance_variables
return {} unless frame_binding
Hash[frame_binding.eval("instance_variables").map { |x| [x, frame_binding.eval(x.to_s)] }]
end

private
def starts_with?(haystack, needle)
haystack[0, needle.length] == needle
Expand Down
64 changes: 50 additions & 14 deletions lib/better_errors/error_page.erb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
background-image: -o-linear-gradient(top, #e4ebfe, #c2d3fe); /* Opera 11.10-12.00 */
background-image: linear-gradient(to bottom, #e4ebfe, #c2d3fe); /* Firefox 16+, IE10, Opera 12.50+ */
}
.name {
.frames .name, .frame_info h2.name {
font-family:Monaco, Incosolata, Consolas, monospace;
font-size:14px;
margin-bottom:4px;
Expand All @@ -83,18 +83,15 @@
border-bottom:1px solid #cccccc;
float:left;
width:50%;
overflow:hidden;
}
.frame_info h2 {
font-family:Monaco, Incosolata, Consolas, monospace;
.frame_info > * {
margin:16px;
}
.frame_info .location {
margin:16px;
.frame_info h2 {
font-family:Monaco, Incosolata, Consolas, monospace;
}
.frame_info .code {
font-family:Monaco, Incosolata, Consolas, monospace;
margin:16px;
background-color:#ffffff;
border:1px solid #cccccc;
border-collapse:collapse;
Expand All @@ -119,6 +116,23 @@
padding:2px 4px;
border:1px solid #d0d0d0;
}
h3 {
font-weight:normal;
border-top:1px solid #cccccc;
padding-top:16px;
}
.var_table {
border-collapse:collapse;
}
.var_table td {
padding:8px;
}
.var_table td.name {
font-style:italic;
}
.var_table tr {
border-bottom:1px solid #cccccc;
}
</style>
</head>
<body>
Expand Down Expand Up @@ -161,7 +175,21 @@
<div class="frame_info" id="frame_info_<%= index %>" style="display:none;">
<h2 class="name"><%= frame.name %></h2>
<div class="location"><span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span></div>
<%= highlighted_code_block frame %>
<%== highlighted_code_block frame %>

<h3>Local Variables</h3>
<table class="var_table">
<% frame.local_variables.each do |name, value| %>
<tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
<% end %>
</table>

<h3>Instance Variables</h3>
<table class="var_table">
<% frame.instance_variables.each do |name, value| %>
<tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
<% end %>
</table>
</div>
<% end %>
<div style="clear:both"></div>
Expand All @@ -176,7 +204,18 @@
var header = document.querySelector("header");
var headerHeight = header.offsetHeight;

function selectFrameInfo(index) {
var el = document.getElementById("frame_info_" + index);

if(previousFrameInfo) {
previousFrameInfo.style.display = "none";
}
previousFrameInfo = el;
previousFrameInfo.style.display = "block";
}

function updateMarginTop() {
return;
if(previousFrameInfo) {
previousFrameInfo.style.marginTop = Math.max(window.scrollY - headerHeight, 0) + "px";
}
Expand All @@ -193,16 +232,13 @@
el.className = "selected";
previous = el;

if(previousFrameInfo) {
previousFrameInfo.style.display = "none";
}
previousFrameInfo = document.getElementById("frame_info_" + el.attributes["data-index"].value);
previousFrameInfo.style.display = "block";

selectFrameInfo(el.attributes["data-index"].value);
updateMarginTop();
};
})(frames[i]);
}

document.querySelector(".frames li:first-child").click();
})();
</script>
</html>
16 changes: 12 additions & 4 deletions lib/better_errors/error_page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ def self.template_path
end

def self.template
Erubis::Eruby.new(File.read(template_path)).tap do |erb|
erb.extend Erubis::EscapeEnhancer
end
Erubis::EscapedEruby.new(File.read(template_path))
end

attr_reader :exception, :env

def initialize(exception, env)
@exception = exception
@exception = real_exception(exception)
@env = env
end

Expand All @@ -24,6 +22,16 @@ def render
end

private
def real_exception(exception)
loop do
case exception
when ActionView::Template::Error; exception = exception.original_exception
else
return exception
end
end
end

def request_path
env["REQUEST_PATH"]
end
Expand Down

0 comments on commit 0cb7986

Please sign in to comment.