better_errors 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +10 -8
- data/lib/better_errors/error_page.rb +3 -1
- data/lib/better_errors/templates/main.erb +103 -26
- data/lib/better_errors/version.rb +1 -1
- metadata +1 -1
data/README.md
CHANGED
|
@@ -2,28 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
* Full stack trace
|
|
10
10
|
* Source code inspection for all stack frames (with highlighting)
|
|
11
11
|
* Local and instance variable inspection
|
|
12
|
-
*
|
|
12
|
+
* Live REPL on every stack frame
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
16
|
Add this line to your application's Gemfile (under the **development** group):
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
```ruby
|
|
19
|
+
gem "better_errors"
|
|
20
|
+
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
If you would like to use Better Errors' **advanced features**, you need to add the [`binding_of_caller`](https://github.com/banister/binding_of_caller) gem to your Gemfile:
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
```ruby
|
|
25
|
+
gem "binding_of_caller"
|
|
26
|
+
```
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
This is an optional dependency however, and Better Errors will work without it.
|
|
27
29
|
|
|
28
30
|
## Usage
|
|
29
31
|
|
|
@@ -30,8 +30,10 @@ module BetterErrors
|
|
|
30
30
|
|
|
31
31
|
def do_eval(opts)
|
|
32
32
|
index = opts["index"].to_i
|
|
33
|
+
binding = backtrace_frames[index].frame_binding
|
|
34
|
+
return { error: "binding_of_caller unavailable" } unless binding
|
|
33
35
|
response = begin
|
|
34
|
-
result =
|
|
36
|
+
result = binding.eval(opts["source"])
|
|
35
37
|
{ result: result.inspect }
|
|
36
38
|
rescue Exception => e
|
|
37
39
|
{ error: (e.inspect rescue e.class.name rescue "Exception") }
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
}
|
|
15
15
|
header {
|
|
16
16
|
padding:32px 32px;
|
|
17
|
-
border-bottom:1px solid #
|
|
17
|
+
border-bottom:1px solid #e64c38;
|
|
18
18
|
background-color: #ffe5e7;
|
|
19
19
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#ffe5e7), to(#ffb2b8)); /* Safari 4+, Chrome */
|
|
20
20
|
background-image: -webkit-linear-gradient(top, #ffe5e7, #ffb2b8); /* Chrome 10+, Safari 5.1+, iOS 5+ */
|
|
@@ -41,6 +41,40 @@
|
|
|
41
41
|
header table th, header table td {
|
|
42
42
|
padding:4px 6px;
|
|
43
43
|
}
|
|
44
|
+
nav {
|
|
45
|
+
display:block;
|
|
46
|
+
padding:12px 12px;
|
|
47
|
+
border-bottom:1px solid #000000;
|
|
48
|
+
background-color: #444444;
|
|
49
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#444444), to(#222222)); /* Safari 4+, Chrome */
|
|
50
|
+
background-image: -webkit-linear-gradient(top, #444444, #222222); /* Chrome 10+, Safari 5.1+, iOS 5+ */
|
|
51
|
+
background-image: -moz-linear-gradient(top, #444444, #222222); /* Firefox 3.6-15 */
|
|
52
|
+
background-image: -o-linear-gradient(top, #444444, #222222); /* Opera 11.10-12.00 */
|
|
53
|
+
background-image: linear-gradient(to bottom, #444444, #222222); /* Firefox 16+, IE10, Opera 12.50+ */
|
|
54
|
+
}
|
|
55
|
+
nav a {
|
|
56
|
+
color:#ffffff;
|
|
57
|
+
text-decoration:none;
|
|
58
|
+
padding:4px 16px;
|
|
59
|
+
border-radius:16px;
|
|
60
|
+
}
|
|
61
|
+
nav a:hover {
|
|
62
|
+
background-color: #666666;
|
|
63
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#666666), to(#444444)); /* Safari 4+, Chrome */
|
|
64
|
+
background-image: -webkit-linear-gradient(top, #666666, #444444); /* Chrome 10+, Safari 5.1+, iOS 5+ */
|
|
65
|
+
background-image: -moz-linear-gradient(top, #666666, #444444); /* Firefox 3.6-15 */
|
|
66
|
+
background-image: -o-linear-gradient(top, #666666, #444444); /* Opera 11.10-12.00 */
|
|
67
|
+
background-image: linear-gradient(to bottom, #666666, #444444); /* Firefox 16+, IE10, Opera 12.50+ */
|
|
68
|
+
}
|
|
69
|
+
nav a.selected {
|
|
70
|
+
color:#000000;
|
|
71
|
+
background-color: #efefef;
|
|
72
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#cfcfcf)); /* Safari 4+, Chrome */
|
|
73
|
+
background-image: -webkit-linear-gradient(top, #efefef, #cfcfcf); /* Chrome 10+, Safari 5.1+, iOS 5+ */
|
|
74
|
+
background-image: -moz-linear-gradient(top, #efefef, #cfcfcf); /* Firefox 3.6-15 */
|
|
75
|
+
background-image: -o-linear-gradient(top, #efefef, #cfcfcf); /* Opera 11.10-12.00 */
|
|
76
|
+
background-image: linear-gradient(to bottom, #efefef, #cfcfcf); /* Firefox 16+, IE10, Opera 12.50+ */
|
|
77
|
+
}
|
|
44
78
|
.frames {
|
|
45
79
|
width:50%;
|
|
46
80
|
float:left;
|
|
@@ -183,6 +217,10 @@
|
|
|
183
217
|
<% end %>
|
|
184
218
|
</table>
|
|
185
219
|
</header>
|
|
220
|
+
<nav>
|
|
221
|
+
<a href="#" id="application_frames">Application Frames</a>
|
|
222
|
+
<a href="#" id="all_frames">All Frames</a>
|
|
223
|
+
</nav>
|
|
186
224
|
<section class="backtrace">
|
|
187
225
|
<ul class="frames">
|
|
188
226
|
<% backtrace_frames.each_with_index do |frame, index| %>
|
|
@@ -205,15 +243,22 @@
|
|
|
205
243
|
<div class="location"><span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span></div>
|
|
206
244
|
<%== highlighted_code_block frame %>
|
|
207
245
|
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
<
|
|
212
|
-
|
|
246
|
+
<% if BetterErrors.binding_of_caller_available? %>
|
|
247
|
+
<div class="repl">
|
|
248
|
+
<h3>REPL</h3>
|
|
249
|
+
<div class="console">
|
|
250
|
+
<pre></pre>
|
|
251
|
+
<div class="prompt">>> <input/></div>
|
|
252
|
+
</div>
|
|
213
253
|
</div>
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
254
|
+
|
|
255
|
+
<div class="variable_info"></div>
|
|
256
|
+
<% else %>
|
|
257
|
+
<h3>Advanced features unavailable</h3>
|
|
258
|
+
<p class="error">
|
|
259
|
+
You must add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
|
|
260
|
+
</p>
|
|
261
|
+
<% end %>
|
|
217
262
|
</div>
|
|
218
263
|
<% end %>
|
|
219
264
|
<div style="clear:both"></div>
|
|
@@ -252,7 +297,7 @@
|
|
|
252
297
|
var el = document.getElementById("frame_info_" + index);
|
|
253
298
|
|
|
254
299
|
var varInfo = el.querySelector(".variable_info");
|
|
255
|
-
if(varInfo.innerHTML == "") {
|
|
300
|
+
if(varInfo && varInfo.innerHTML == "") {
|
|
256
301
|
apiCall("variables", { "index": index }, function(response) {
|
|
257
302
|
if(response.error) {
|
|
258
303
|
varInfo.innerHTML = "<span class='error'>" + escapeHTML(response.error) + "</span>";
|
|
@@ -268,7 +313,10 @@
|
|
|
268
313
|
previousFrameInfo = el;
|
|
269
314
|
previousFrameInfo.style.display = "block";
|
|
270
315
|
|
|
271
|
-
el.querySelector(".repl input")
|
|
316
|
+
var replInput = el.querySelector(".repl input");
|
|
317
|
+
if(replInput) {
|
|
318
|
+
replInput.focus();
|
|
319
|
+
}
|
|
272
320
|
}
|
|
273
321
|
|
|
274
322
|
for(var i = 0; i < frames.length; i++) {
|
|
@@ -284,25 +332,54 @@
|
|
|
284
332
|
};
|
|
285
333
|
var replPre = frameInfo.querySelector(".repl pre");
|
|
286
334
|
var replInput = frameInfo.querySelector(".repl input");
|
|
287
|
-
replInput
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
335
|
+
if(replInput) {
|
|
336
|
+
replInput.onkeydown = function(ev) {
|
|
337
|
+
if(ev.keyCode == 13) {
|
|
338
|
+
var text = replInput.value;
|
|
339
|
+
replInput.value = "";
|
|
340
|
+
apiCall("eval", { "index": index, source: text }, function(response) {
|
|
341
|
+
replPre.innerHTML += ">> " + response.highlighted_input + "\n";
|
|
342
|
+
if(response.error) {
|
|
343
|
+
replPre.innerHTML += "!! " + escapeHTML(response.error) + "\n";
|
|
344
|
+
} else {
|
|
345
|
+
replPre.innerHTML += "=> " + escapeHTML(response.result) + "\n";
|
|
346
|
+
}
|
|
347
|
+
replPre.scrollTop = replPre.offsetHeight;
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
302
352
|
})(i, frames[i], frameInfos[i]);
|
|
303
353
|
}
|
|
304
354
|
|
|
305
355
|
document.querySelector(".frames li:first-child").click();
|
|
356
|
+
|
|
357
|
+
var applicationFrames = document.getElementById("application_frames");
|
|
358
|
+
var allFrames = document.getElementById("all_frames");
|
|
359
|
+
|
|
360
|
+
applicationFrames.onclick = function() {
|
|
361
|
+
allFrames.className = "";
|
|
362
|
+
applicationFrames.className = "selected";
|
|
363
|
+
for(var i = 0; i < frames.length; i++) {
|
|
364
|
+
if(frames[i].attributes["data-context"].value == "application") {
|
|
365
|
+
frames[i].style.display = "block";
|
|
366
|
+
} else {
|
|
367
|
+
frames[i].style.display = "none";
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
allFrames.onclick = function() {
|
|
374
|
+
applicationFrames.className = "";
|
|
375
|
+
allFrames.className = "selected";
|
|
376
|
+
for(var i = 0; i < frames.length; i++) {
|
|
377
|
+
frames[i].style.display = "block";
|
|
378
|
+
}
|
|
379
|
+
return false;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
applicationFrames.click();
|
|
306
383
|
})();
|
|
307
384
|
</script>
|
|
308
385
|
</html>
|