better_errors 0.1.1 → 0.2.0
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.
Potentially problematic release.
This version of better_errors might be problematic. Click here for more details.
- data/README.md +1 -1
- data/lib/better_errors/code_formatter.rb +1 -1
- data/lib/better_errors/stack_frame.rb +17 -7
- data/lib/better_errors/templates/main.erb +703 -241
- data/lib/better_errors/templates/variable_info.erb +20 -12
- data/lib/better_errors/version.rb +1 -1
- data/lib/better_errors.rb +3 -3
- data/spec/better_errors/stack_frame_spec.rb +14 -0
- metadata +2 -1
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
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 in any Rack app as Rack middleware.
|
4
4
|
|
5
|
-

|
6
6
|
|
7
7
|
## Features
|
8
8
|
|
@@ -4,7 +4,7 @@ module BetterErrors
|
|
4
4
|
idx_offset = 0
|
5
5
|
list = exception.backtrace.each_with_index.map do |frame, idx|
|
6
6
|
frame_binding = exception.__better_errors_bindings_stack[idx - idx_offset]
|
7
|
-
md = /\A(?<file>.*):(?<line>\d*):in `(?<name>.*)'
|
7
|
+
md = /\A(?<file>.*):(?<line>\d*)(:in `(?<name>.*)')?\z/.match(frame)
|
8
8
|
|
9
9
|
# prevent mismatching frames in the backtrace with the binding stack
|
10
10
|
if frame_binding and frame_binding.eval("__FILE__") != md[:file]
|
@@ -53,6 +53,14 @@ module BetterErrors
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
def class_name
|
58
|
+
@class_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_name
|
62
|
+
@method_name || @name
|
63
|
+
end
|
56
64
|
|
57
65
|
def context
|
58
66
|
if application?
|
@@ -99,12 +107,14 @@ module BetterErrors
|
|
99
107
|
def set_pretty_method_name
|
100
108
|
name =~ /\A(block (\([^)]+\) )?in )?/
|
101
109
|
recv = frame_binding.eval("self")
|
102
|
-
return unless
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
110
|
+
return unless method_name = frame_binding.eval("__method__")
|
111
|
+
if recv.is_a? Module
|
112
|
+
@class_name = "#{$1}#{recv}"
|
113
|
+
@method_name = ".#{method_name}"
|
114
|
+
else
|
115
|
+
@class_name = "#{$1}#{recv.class}"
|
116
|
+
@method_name = "##{method_name}"
|
117
|
+
end
|
108
118
|
end
|
109
119
|
|
110
120
|
def starts_with?(haystack, needle)
|
@@ -3,264 +3,722 @@
|
|
3
3
|
<head>
|
4
4
|
<title><%= exception.class %> at <%= request_path %></title>
|
5
5
|
<style>
|
6
|
+
/* Basic reset */
|
6
7
|
* {
|
7
|
-
margin:0;
|
8
|
-
padding:0;
|
8
|
+
margin: 0;
|
9
|
+
padding: 0;
|
9
10
|
}
|
11
|
+
|
12
|
+
table {
|
13
|
+
width: 100%;
|
14
|
+
border-collapse: collapse;
|
15
|
+
}
|
16
|
+
|
17
|
+
th, td {
|
18
|
+
vertical-align: top;
|
19
|
+
text-align: left;
|
20
|
+
}
|
21
|
+
|
22
|
+
textarea {
|
23
|
+
resize: none;
|
24
|
+
}
|
25
|
+
|
10
26
|
body {
|
11
|
-
font-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
background
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
background
|
94
|
-
border-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
.
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
.
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
overflow:
|
134
|
-
}
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
.
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
}
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
}
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
27
|
+
font-size: 10pt;
|
28
|
+
}
|
29
|
+
|
30
|
+
body, td, input, textarea {
|
31
|
+
font-family: helvetica neue, lucida grande, sans-serif;
|
32
|
+
line-height: 1.5;
|
33
|
+
color: #333;
|
34
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
35
|
+
}
|
36
|
+
|
37
|
+
html {
|
38
|
+
background: #f0f0f5;
|
39
|
+
}
|
40
|
+
|
41
|
+
/* ---------------------------------------------------------------------
|
42
|
+
* Basic layout
|
43
|
+
* --------------------------------------------------------------------- */
|
44
|
+
|
45
|
+
/* Small */
|
46
|
+
@media screen and (max-width: 1100px) {
|
47
|
+
html {
|
48
|
+
overflow-y: scroll;
|
49
|
+
}
|
50
|
+
|
51
|
+
body {
|
52
|
+
margin: 0 20px;
|
53
|
+
}
|
54
|
+
|
55
|
+
header.exception {
|
56
|
+
margin: 0 -20px;
|
57
|
+
}
|
58
|
+
|
59
|
+
nav.sidebar {
|
60
|
+
padding: 0;
|
61
|
+
margin: 20px 0;
|
62
|
+
}
|
63
|
+
|
64
|
+
ul.frames {
|
65
|
+
max-height: 200px;
|
66
|
+
overflow: auto;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
/* Wide */
|
71
|
+
@media screen and (min-width: 1100px) {
|
72
|
+
header.exception {
|
73
|
+
position: fixed;
|
74
|
+
top: 0;
|
75
|
+
left: 0;
|
76
|
+
right: 0;
|
77
|
+
}
|
78
|
+
|
79
|
+
nav.sidebar,
|
80
|
+
.frame_info {
|
81
|
+
position: fixed;
|
82
|
+
top: 95px;
|
83
|
+
bottom: 0;
|
84
|
+
|
85
|
+
box-sizing: border-box;
|
86
|
+
|
87
|
+
overflow-y: auto;
|
88
|
+
overflow-x: hidden;
|
89
|
+
}
|
90
|
+
|
91
|
+
nav.sidebar {
|
92
|
+
width: 40%;
|
93
|
+
left: 20px;
|
94
|
+
top: 115px;
|
95
|
+
bottom: 20px;
|
96
|
+
}
|
97
|
+
|
98
|
+
.frame_info {
|
99
|
+
right: 0;
|
100
|
+
left: 40%;
|
101
|
+
|
102
|
+
padding: 20px;
|
103
|
+
padding-left: 10px;
|
104
|
+
margin-left: 30px;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
nav.sidebar {
|
109
|
+
background: #d3d3da;
|
110
|
+
border-top: solid 3px #a33;
|
111
|
+
border-bottom: solid 3px #a33;
|
112
|
+
border-radius: 4px;
|
113
|
+
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
114
|
+
}
|
115
|
+
|
116
|
+
/* ---------------------------------------------------------------------
|
117
|
+
* Header
|
118
|
+
* --------------------------------------------------------------------- */
|
119
|
+
|
120
|
+
header.exception {
|
121
|
+
padding: 18px 20px;
|
122
|
+
|
123
|
+
height: 59px;
|
124
|
+
min-height: 59px;
|
125
|
+
|
126
|
+
overflow: hidden;
|
127
|
+
|
128
|
+
background-color: #20202a;
|
129
|
+
color: #aaa;
|
130
|
+
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
|
131
|
+
font-weight: 200;
|
132
|
+
box-shadow: inset 0 -5px 3px -3px rgba(0, 0, 0, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
|
133
|
+
|
134
|
+
-webkit-text-smoothing: antialiased;
|
135
|
+
}
|
136
|
+
|
137
|
+
/* Heading */
|
138
|
+
header.exception h2 {
|
139
|
+
font-weight: 200;
|
140
|
+
font-size: 11pt;
|
141
|
+
}
|
142
|
+
|
143
|
+
header.exception h2,
|
144
|
+
header.exception p {
|
145
|
+
line-height: 1.4em;
|
146
|
+
height: 1.4em;
|
147
|
+
overflow: hidden;
|
148
|
+
white-space: pre;
|
149
|
+
text-overflow: ellipsis;
|
150
|
+
}
|
151
|
+
|
152
|
+
header.exception h2 strong {
|
153
|
+
font-weight: 700;
|
154
|
+
color: #d55;
|
155
|
+
}
|
156
|
+
|
157
|
+
header.exception p {
|
158
|
+
font-weight: 200;
|
159
|
+
font-size: 20pt;
|
160
|
+
color: white;
|
161
|
+
}
|
162
|
+
|
163
|
+
header.exception:hover {
|
164
|
+
height: auto;
|
165
|
+
z-index: 2;
|
166
|
+
}
|
167
|
+
|
168
|
+
header.exception:hover h2,
|
169
|
+
header.exception:hover p {
|
170
|
+
padding-right: 20px;
|
171
|
+
overflow-y: auto;
|
172
|
+
word-wrap: break-word;
|
173
|
+
height: auto;
|
174
|
+
max-height: 7em;
|
175
|
+
}
|
176
|
+
|
177
|
+
@media screen and (max-width: 1100px) {
|
178
|
+
header.exception {
|
179
|
+
height: auto;
|
180
|
+
}
|
181
|
+
|
182
|
+
header.exception h2,
|
183
|
+
header.exception p {
|
184
|
+
padding-right: 20px;
|
185
|
+
overflow-y: auto;
|
186
|
+
word-wrap: break-word;
|
187
|
+
height: auto;
|
188
|
+
max-height: 7em;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
<%#
|
193
|
+
/* Light theme */
|
194
|
+
header.exception {
|
195
|
+
text-shadow: 0 1px 0 rgba(250, 250, 250, 0.6);
|
196
|
+
background: rgba(200,100,50,0.10);
|
197
|
+
color: #977;
|
198
|
+
}
|
199
|
+
header.exception h2 strong {
|
200
|
+
color: #533;
|
201
|
+
}
|
202
|
+
header.exception p {
|
203
|
+
color: #744;
|
204
|
+
}
|
205
|
+
%>
|
206
|
+
|
207
|
+
/* ---------------------------------------------------------------------
|
208
|
+
* Navigation
|
209
|
+
* --------------------------------------------------------------------- */
|
210
|
+
|
211
|
+
nav.tabs {
|
212
|
+
border-bottom: solid 1px #ddd;
|
213
|
+
|
214
|
+
background-color: #eee;
|
215
|
+
text-align: center;
|
216
|
+
|
217
|
+
padding: 6px;
|
218
|
+
|
219
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
220
|
+
}
|
221
|
+
|
222
|
+
nav.tabs a {
|
223
|
+
display: inline-block;
|
224
|
+
|
225
|
+
height: 22px;
|
226
|
+
line-height: 22px;
|
227
|
+
padding: 0 10px;
|
228
|
+
|
229
|
+
text-decoration: none;
|
230
|
+
font-size: 8pt;
|
231
|
+
font-weight: bold;
|
232
|
+
|
233
|
+
color: #999;
|
234
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
235
|
+
}
|
236
|
+
|
237
|
+
nav.tabs a.selected {
|
238
|
+
color: white;
|
239
|
+
background: rgba(0, 0, 0, 0.5);
|
240
|
+
border-radius: 16px;
|
241
|
+
box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.1);
|
242
|
+
text-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.4);
|
243
|
+
}
|
244
|
+
|
245
|
+
/* ---------------------------------------------------------------------
|
246
|
+
* Sidebar
|
247
|
+
* --------------------------------------------------------------------- */
|
248
|
+
|
249
|
+
ul.frames {
|
250
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
251
|
+
}
|
252
|
+
|
253
|
+
/* Each item */
|
254
|
+
ul.frames li {
|
255
|
+
background-color: #f8f8f8;
|
256
|
+
background: -webkit-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
257
|
+
background: -moz-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
258
|
+
background: linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
259
|
+
box-shadow: inset 0 -1px 0 #e2e2e2;
|
260
|
+
padding: 7px 20px;
|
261
|
+
|
262
|
+
cursor: pointer;
|
263
|
+
overflow: hidden;
|
264
|
+
}
|
265
|
+
|
266
|
+
ul.frames .name,
|
267
|
+
ul.frames .location {
|
268
|
+
overflow: hidden;
|
269
|
+
height: 1.5em;
|
270
|
+
|
271
|
+
white-space: nowrap;
|
272
|
+
word-wrap: none;
|
273
|
+
text-overflow: ellipsis;
|
274
|
+
}
|
275
|
+
|
276
|
+
ul.frames .method {
|
277
|
+
color: #966;
|
278
|
+
}
|
279
|
+
|
280
|
+
ul.frames .location {
|
281
|
+
font-size: 0.85em;
|
282
|
+
font-weight: 400;
|
283
|
+
color: #999;
|
284
|
+
}
|
285
|
+
|
286
|
+
ul.frames .line {
|
287
|
+
font-weight: bold;
|
288
|
+
}
|
289
|
+
|
290
|
+
/* Selected frame */
|
291
|
+
ul.frames li.selected {
|
292
|
+
background: #38a;
|
293
|
+
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), inset 0 2px 0 rgba(255, 255, 255, 0.01), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
|
294
|
+
}
|
295
|
+
|
296
|
+
ul.frames li.selected .name,
|
297
|
+
ul.frames li.selected .method,
|
298
|
+
ul.frames li.selected .location {
|
299
|
+
color: white;
|
300
|
+
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
|
301
|
+
}
|
302
|
+
|
303
|
+
ul.frames li.selected .location {
|
304
|
+
opacity: 0.6;
|
305
|
+
}
|
306
|
+
|
307
|
+
/* Iconography */
|
308
|
+
ul.frames li {
|
309
|
+
padding-left: 60px;
|
310
|
+
position: relative;
|
311
|
+
}
|
312
|
+
|
313
|
+
ul.frames li .icon {
|
314
|
+
display: block;
|
315
|
+
width: 20px;
|
316
|
+
height: 20px;
|
317
|
+
line-height: 20px;
|
318
|
+
border-radius: 15px;
|
319
|
+
|
320
|
+
text-align: center;
|
321
|
+
|
322
|
+
background: white;
|
323
|
+
border: solid 2px #ccc;
|
324
|
+
|
325
|
+
font-size: 9pt;
|
326
|
+
font-weight: 200;
|
327
|
+
font-style: normal;
|
328
|
+
|
329
|
+
position: absolute;
|
330
|
+
top: 14px;
|
331
|
+
left: 20px;
|
332
|
+
}
|
333
|
+
|
334
|
+
ul.frames .icon.application {
|
335
|
+
background: #808090;
|
336
|
+
border-color: #555;
|
337
|
+
}
|
338
|
+
|
339
|
+
ul.frames .icon.application:before {
|
340
|
+
content: 'A';
|
341
|
+
color: white;
|
342
|
+
text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
|
198
343
|
}
|
344
|
+
|
345
|
+
/* Responsiveness -- flow to single-line mode */
|
346
|
+
@media screen and (max-width: 1100px) {
|
347
|
+
ul.frames li {
|
348
|
+
padding-top: 6px;
|
349
|
+
padding-bottom: 6px;
|
350
|
+
padding-left: 36px;
|
351
|
+
line-height: 1.3;
|
352
|
+
}
|
353
|
+
|
354
|
+
ul.frames li .icon {
|
355
|
+
width: 11px;
|
356
|
+
height: 11px;
|
357
|
+
line-height: 11px;
|
358
|
+
|
359
|
+
top: 7px;
|
360
|
+
left: 10px;
|
361
|
+
font-size: 5pt;
|
362
|
+
}
|
363
|
+
|
364
|
+
ul.frames .name,
|
365
|
+
ul.frames .location {
|
366
|
+
display: inline-block;
|
367
|
+
line-height: 1.3;
|
368
|
+
height: 1.3em;
|
369
|
+
}
|
370
|
+
|
371
|
+
ul.frames .name {
|
372
|
+
margin-right: 10px;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
/* ---------------------------------------------------------------------
|
377
|
+
* Monospace
|
378
|
+
* --------------------------------------------------------------------- */
|
379
|
+
|
380
|
+
pre, code, .repl input, .repl .prompt span, textarea {
|
381
|
+
font-family: menlo, lucida console, monospace;
|
382
|
+
font-size: 8pt;
|
383
|
+
}
|
384
|
+
|
385
|
+
/* ---------------------------------------------------------------------
|
386
|
+
* Display area
|
387
|
+
* --------------------------------------------------------------------- */
|
388
|
+
|
389
|
+
.trace_info {
|
390
|
+
background: #fff;
|
391
|
+
padding: 6px;
|
392
|
+
border-radius: 3px;
|
393
|
+
margin-bottom: 2px;
|
394
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.03), 1px 1px 0 rgba(0, 0, 0, 0.05), -1px 1px 0 rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(0, 0, 0, 0.04);
|
395
|
+
}
|
396
|
+
|
397
|
+
/* Titlebar */
|
398
|
+
.trace_info .title {
|
399
|
+
background: #f1f1f1;
|
400
|
+
|
401
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
402
|
+
overflow: hidden;
|
403
|
+
padding: 6px 10px;
|
404
|
+
|
405
|
+
border: solid 1px #ccc;
|
406
|
+
border-bottom: 0;
|
407
|
+
|
408
|
+
border-top-left-radius: 2px;
|
409
|
+
border-top-right-radius: 2px;
|
410
|
+
}
|
411
|
+
|
412
|
+
.trace_info .title .name,
|
413
|
+
.trace_info .title .location {
|
414
|
+
font-size: 9pt;
|
415
|
+
line-height: 26px;
|
416
|
+
height: 26px;
|
417
|
+
overflow: hidden;
|
418
|
+
}
|
419
|
+
|
420
|
+
.trace_info .title .location {
|
421
|
+
float: left;
|
422
|
+
font-weight: bold;
|
423
|
+
font-size: 10pt;
|
424
|
+
}
|
425
|
+
|
426
|
+
.trace_info .title .name {
|
427
|
+
float: right;
|
428
|
+
font-weight: 200;
|
429
|
+
}
|
430
|
+
|
431
|
+
.code, .console, .unavailable {
|
432
|
+
background: #fff;
|
433
|
+
padding: 5px;
|
434
|
+
|
435
|
+
box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
436
|
+
}
|
437
|
+
|
438
|
+
.code {
|
439
|
+
margin-bottom: -1px;
|
440
|
+
}
|
441
|
+
|
442
|
+
.code {
|
443
|
+
padding: 10px 0;
|
444
|
+
overflow: auto;
|
445
|
+
}
|
446
|
+
|
447
|
+
/* Source unavailable */
|
448
|
+
p.unavailable {
|
449
|
+
padding: 20px 0 40px 0;
|
450
|
+
text-align: center;
|
451
|
+
color: #b99;
|
452
|
+
font-weight: bold;
|
453
|
+
}
|
454
|
+
|
455
|
+
p.unavailable:before {
|
456
|
+
content: '\00d7';
|
457
|
+
display: block;
|
458
|
+
|
459
|
+
color: #daa;
|
460
|
+
|
461
|
+
text-align: center;
|
462
|
+
font-size: 40pt;
|
463
|
+
font-weight: normal;
|
464
|
+
margin-bottom: -10px;
|
465
|
+
}
|
466
|
+
|
467
|
+
@-webkit-keyframes highlight {
|
468
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
469
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
470
|
+
}
|
471
|
+
@-moz-keyframes highlight {
|
472
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
473
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
474
|
+
}
|
475
|
+
@keyframes highlight {
|
476
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
477
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
478
|
+
}
|
479
|
+
|
480
|
+
.code .highlight {
|
481
|
+
background: rgba(220, 30, 30, 0.1);
|
482
|
+
-webkit-animation: highlight 400ms linear 1;
|
483
|
+
-moz-animation: highlight 400ms linear 1;
|
484
|
+
animation: highlight 400ms linear 1;
|
485
|
+
}
|
486
|
+
|
487
|
+
/* REPL shell */
|
488
|
+
.console {
|
489
|
+
padding: 0 1px 10px 1px;
|
490
|
+
border-bottom-left-radius: 2px;
|
491
|
+
border-bottom-right-radius: 2px;
|
492
|
+
}
|
493
|
+
|
494
|
+
.console pre {
|
495
|
+
padding: 10px 10px 0 10px;
|
496
|
+
max-height: 200px;
|
497
|
+
overflow-x: none;
|
498
|
+
overflow-y: auto;
|
499
|
+
margin-bottom: -3px;
|
500
|
+
word-wrap: break-word;
|
501
|
+
white-space: pre-wrap;
|
502
|
+
}
|
503
|
+
|
504
|
+
/* .prompt > span + input */
|
505
|
+
.console .prompt {
|
506
|
+
display: table;
|
507
|
+
width: 100%;
|
508
|
+
}
|
509
|
+
|
510
|
+
.console .prompt span,
|
511
|
+
.console .prompt input {
|
512
|
+
display: table-cell;
|
513
|
+
}
|
514
|
+
|
515
|
+
.console .prompt span {
|
516
|
+
width: 1%;
|
517
|
+
padding-right: 5px;
|
518
|
+
padding-left: 10px;
|
519
|
+
}
|
520
|
+
|
521
|
+
.console .prompt input {
|
522
|
+
width: 99%;
|
523
|
+
}
|
524
|
+
|
525
|
+
/* Input box */
|
526
|
+
.console input,
|
527
|
+
.console input:focus {
|
528
|
+
outline: 0;
|
529
|
+
border: 0;
|
530
|
+
padding: 0;
|
531
|
+
background: transparent;
|
532
|
+
margin: 0;
|
533
|
+
}
|
534
|
+
|
535
|
+
/* Hint text */
|
536
|
+
.hint {
|
537
|
+
margin: 15px 0 20px 0;
|
538
|
+
font-size: 8pt;
|
539
|
+
color: #8080a0;
|
540
|
+
padding-left: 20px;
|
541
|
+
}
|
542
|
+
|
543
|
+
.hint:before {
|
544
|
+
content: '\25b2';
|
545
|
+
margin-right: 5px;
|
546
|
+
opacity: 0.5;
|
547
|
+
}
|
548
|
+
|
549
|
+
/* ---------------------------------------------------------------------
|
550
|
+
* Variable infos
|
551
|
+
* --------------------------------------------------------------------- */
|
552
|
+
|
553
|
+
.sub {
|
554
|
+
padding: 10px 0;
|
555
|
+
margin: 10px 0;
|
556
|
+
}
|
557
|
+
|
558
|
+
.sub:before {
|
559
|
+
content: '';
|
560
|
+
display: block;
|
561
|
+
width: 100%;
|
562
|
+
height: 4px;
|
563
|
+
|
564
|
+
border-radius: 2px;
|
565
|
+
background: rgba(0, 150, 200, 0.05);
|
566
|
+
box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04), inset 2px 2px 2px rgba(0, 0, 0, 0.07);
|
567
|
+
}
|
568
|
+
|
569
|
+
.sub h3 {
|
570
|
+
color: #39a;
|
571
|
+
font-size: 1.1em;
|
572
|
+
margin: 10px 0;
|
573
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
574
|
+
|
575
|
+
-webkit-font-smoothing: antialiased;
|
576
|
+
}
|
577
|
+
|
578
|
+
.sub .inset {
|
579
|
+
overflow-y: auto;
|
580
|
+
}
|
581
|
+
|
582
|
+
.sub table {
|
583
|
+
table-layout: fixed;
|
584
|
+
}
|
585
|
+
|
586
|
+
.sub table td {
|
587
|
+
border-top: dotted 1px #ddd;
|
588
|
+
padding: 7px 1px;
|
589
|
+
}
|
590
|
+
|
591
|
+
.sub table td.name {
|
592
|
+
width: 150px;
|
593
|
+
|
594
|
+
font-weight: bold;
|
595
|
+
font-size: 0.8em;
|
596
|
+
padding-right: 20px;
|
597
|
+
}
|
598
|
+
|
599
|
+
.sub table td pre {
|
600
|
+
max-height: 15em;
|
601
|
+
overflow-y: auto;
|
602
|
+
}
|
603
|
+
|
604
|
+
.sub table td pre {
|
605
|
+
width: 100%;
|
606
|
+
|
607
|
+
word-wrap: break-word;
|
608
|
+
white-space: normal;
|
609
|
+
}
|
610
|
+
|
611
|
+
/* ---------------------------------------------------------------------
|
612
|
+
* Scrollbar
|
613
|
+
* --------------------------------------------------------------------- */
|
614
|
+
|
615
|
+
nav.sidebar::-webkit-scrollbar,
|
616
|
+
.inset pre::-webkit-scrollbar,
|
617
|
+
.console pre::-webkit-scrollbar,
|
618
|
+
.code::-webkit-scrollbar {
|
619
|
+
width: 10px;
|
620
|
+
height: 10px;
|
621
|
+
}
|
622
|
+
|
623
|
+
.inset pre::-webkit-scrollbar-thumb,
|
624
|
+
.console pre::-webkit-scrollbar-thumb,
|
625
|
+
.code::-webkit-scrollbar-thumb {
|
626
|
+
background: #ccc;
|
627
|
+
border-radius: 5px;
|
628
|
+
}
|
629
|
+
|
630
|
+
nav.sidebar::-webkit-scrollbar-thumb {
|
631
|
+
background: rgba(0, 0, 0, 0.0);
|
632
|
+
border-radius: 5px;
|
633
|
+
}
|
634
|
+
|
635
|
+
nav.sidebar:hover::-webkit-scrollbar-thumb {
|
636
|
+
background-color: #999;
|
637
|
+
background: -webkit-linear-gradient(left, #aaa, #999);
|
638
|
+
}
|
639
|
+
|
640
|
+
.console pre:hover::-webkit-scrollbar-thumb,
|
641
|
+
.inset pre:hover::-webkit-scrollbar-thumb,
|
642
|
+
.code:hover::-webkit-scrollbar-thumb {
|
643
|
+
background: #888;
|
644
|
+
}
|
645
|
+
|
646
|
+
|
199
647
|
</style>
|
200
648
|
</head>
|
201
649
|
<body>
|
202
|
-
<
|
203
|
-
<
|
204
|
-
|
205
|
-
<
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
<% if backtrace_frames.any? %>
|
210
|
-
<tr>
|
211
|
-
<th>File</th>
|
212
|
-
<td><%= backtrace_frames.first.filename %></td>
|
213
|
-
</tr>
|
214
|
-
<tr>
|
215
|
-
<th>Line</th>
|
216
|
-
<td><%= backtrace_frames.first.line %></td>
|
217
|
-
</tr>
|
218
|
-
<% end %>
|
219
|
-
</table>
|
220
|
-
</header>
|
221
|
-
<nav>
|
222
|
-
<a href="#" id="application_frames">Application Frames</a>
|
223
|
-
<a href="#" id="all_frames">All Frames</a>
|
224
|
-
</nav>
|
650
|
+
<div class='top'>
|
651
|
+
<header class="exception">
|
652
|
+
<h2><strong><%= exception.class %></strong> <span>at <%= request_path %></span></h2>
|
653
|
+
<p><%= exception_message %></p>
|
654
|
+
</header>
|
655
|
+
</div>
|
656
|
+
|
225
657
|
<section class="backtrace">
|
226
|
-
<
|
227
|
-
|
228
|
-
<
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
658
|
+
<nav class="sidebar">
|
659
|
+
<nav class="tabs">
|
660
|
+
<a href="#" id="application_frames">Application Frames</a>
|
661
|
+
<a href="#" id="all_frames">All Frames</a>
|
662
|
+
</nav>
|
663
|
+
<ul class="frames">
|
664
|
+
<% backtrace_frames.each_with_index do |frame, index| %>
|
665
|
+
<li
|
666
|
+
class="<%= frame.context %>"
|
667
|
+
style="display: none"
|
668
|
+
data-context="<%= frame.context %>"
|
669
|
+
data-full-filename="<%= frame.filename %>"
|
670
|
+
data-filename="<%= frame.pretty_path %>"
|
671
|
+
data-line="<%= frame.line %>"
|
672
|
+
data-name="<%= frame.name %>"
|
673
|
+
data-index="<%= index %>"
|
674
|
+
>
|
675
|
+
<span class='stroke'></span>
|
676
|
+
<i class="icon <%= frame.context %>"></i>
|
677
|
+
<div class="info">
|
678
|
+
<div class="name">
|
679
|
+
<strong><%= frame.class_name %></strong><span class='method'><%= frame.method_name %></span>
|
680
|
+
</div>
|
681
|
+
<div class="location">
|
682
|
+
<span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span>
|
683
|
+
</div>
|
684
|
+
</div>
|
685
|
+
</li>
|
686
|
+
<% end %>
|
687
|
+
</ul>
|
688
|
+
</nav>
|
689
|
+
|
241
690
|
<% backtrace_frames.each_with_index do |frame, index| %>
|
242
691
|
<div class="frame_info" id="frame_info_<%= index %>" style="display:none;">
|
243
|
-
<
|
244
|
-
|
245
|
-
|
692
|
+
<header class="trace_info">
|
693
|
+
<div class="title">
|
694
|
+
<h2 class="name"><%= frame.name %></h2>
|
695
|
+
<div class="location"><span class="filename"><%= frame.pretty_path %></span></div>
|
696
|
+
</div>
|
697
|
+
|
698
|
+
<%== highlighted_code_block frame %>
|
246
699
|
|
247
|
-
|
248
|
-
<% if frame.frame_binding %>
|
700
|
+
<% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
|
249
701
|
<div class="repl">
|
250
|
-
<h3>REPL</h3>
|
251
702
|
<div class="console">
|
252
703
|
<pre></pre>
|
253
704
|
<div class="prompt"><span>>></span> <input/></div>
|
254
705
|
</div>
|
255
706
|
</div>
|
256
|
-
|
257
|
-
<div class="variable_info"></div>
|
258
707
|
<% end %>
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
708
|
+
</header>
|
709
|
+
|
710
|
+
<% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
|
711
|
+
<div class="hint">
|
712
|
+
This a live shell. Type in here.
|
713
|
+
</div>
|
714
|
+
|
715
|
+
<div class="variable_info"></div>
|
716
|
+
<% end %>
|
717
|
+
|
718
|
+
<% unless BetterErrors.binding_of_caller_available? %>
|
719
|
+
<div class="hint">
|
720
|
+
<strong>Tip:</strong> add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
|
721
|
+
</div>
|
264
722
|
<% end %>
|
265
723
|
</div>
|
266
724
|
<% end %>
|
@@ -448,7 +906,11 @@
|
|
448
906
|
})(i);
|
449
907
|
}
|
450
908
|
|
451
|
-
|
909
|
+
// Click the first application frame
|
910
|
+
(
|
911
|
+
document.querySelector(".frames li.application") ||
|
912
|
+
document.querySelector(".frames li")
|
913
|
+
).click();
|
452
914
|
|
453
915
|
var applicationFramesButton = document.getElementById("application_frames");
|
454
916
|
var allFramesButton = document.getElementById("all_frames");
|
@@ -1,13 +1,21 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
|
4
|
-
<
|
5
|
-
|
6
|
-
|
1
|
+
<div class="sub">
|
2
|
+
<h3>Local Variables</h3>
|
3
|
+
<div class='inset variables'>
|
4
|
+
<table class="var_table">
|
5
|
+
<% @frame.local_variables.each do |name, value| %>
|
6
|
+
<tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
|
7
|
+
<% end %>
|
8
|
+
</table>
|
9
|
+
</div>
|
10
|
+
</div>
|
7
11
|
|
8
|
-
<
|
9
|
-
<
|
10
|
-
|
11
|
-
<
|
12
|
-
|
13
|
-
|
12
|
+
<div class="sub">
|
13
|
+
<h3>Instance Variables</h3>
|
14
|
+
<div class="inset variables">
|
15
|
+
<table class="var_table">
|
16
|
+
<% @frame.instance_variables.each do |name, value| %>
|
17
|
+
<tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
|
18
|
+
<% end %>
|
19
|
+
</table>
|
20
|
+
</div>
|
21
|
+
</div>
|
data/lib/better_errors.rb
CHANGED
@@ -22,12 +22,12 @@ rescue LoadError => e
|
|
22
22
|
BetterErrors.binding_of_caller_available = false
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
require "better_errors/core_ext/exception"
|
27
|
-
else
|
25
|
+
unless BetterErrors.binding_of_caller_available?
|
28
26
|
warn "BetterErrors: binding_of_caller gem unavailable, cannot display local variables on error pages."
|
29
27
|
warn "Add 'binding_of_caller' to your Gemfile to make this warning go away."
|
30
28
|
warn ""
|
31
29
|
end
|
32
30
|
|
31
|
+
require "better_errors/core_ext/exception"
|
32
|
+
|
33
33
|
require "better_errors/rails" if defined? Rails::Railtie
|
@@ -66,5 +66,19 @@ module BetterErrors
|
|
66
66
|
frames.first.filename.should == "my_file.rb"
|
67
67
|
frames.first.line.should == 123
|
68
68
|
end
|
69
|
+
|
70
|
+
it "should not blow up if no method name is given" do
|
71
|
+
error = StandardError.new
|
72
|
+
|
73
|
+
error.stub!(:backtrace).and_return(["foo.rb:123"])
|
74
|
+
frames = StackFrame.from_exception(error)
|
75
|
+
frames.first.filename.should == "foo.rb"
|
76
|
+
frames.first.line.should == 123
|
77
|
+
|
78
|
+
error.stub!(:backtrace).and_return(["foo.rb:123: this is an error message"])
|
79
|
+
frames = StackFrame.from_exception(error)
|
80
|
+
frames.first.filename.should == "foo.rb"
|
81
|
+
frames.first.line.should == 123
|
82
|
+
end
|
69
83
|
end
|
70
84
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_errors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -127,3 +127,4 @@ test_files:
|
|
127
127
|
- spec/better_errors/stack_frame_spec.rb
|
128
128
|
- spec/better_errors/support/my_source.rb
|
129
129
|
- spec/spec_helper.rb
|
130
|
+
has_rdoc:
|