better_errors 1.0.1 → 1.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/better_errors/error_page.rb +1 -1
- data/lib/better_errors/stack_frame.rb +14 -13
- data/lib/better_errors/templates/main.erb +59 -45
- data/lib/better_errors/version.rb +1 -1
- data/spec/better_errors/middleware_spec.rb +34 -0
- data/spec/better_errors/repl/pry_spec.rb +5 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe0694430a61558b1ad22a156922e9a162b02352
|
4
|
+
data.tar.gz: 6804d151297037d1eb778143d3eb807fe7573e9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d0c58b00e4b6965e8dfd3ae3ded8a9efbfde40f8878854cf3ed86b46a5b344e647a73e24f541de858ea1f9f1b6b6c5b29145896b73870ac3eb34219edafb9db
|
7
|
+
data.tar.gz: 5fc01d0bd170e712c28d0efde81fa177eff86b6b36862bef1217749e1b39778c6e97e1899bed429f66dfaecfee45de843328935fe746402508892657232cf7aa
|
data/CHANGELOG.md
ADDED
@@ -87,7 +87,7 @@ module BetterErrors
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def real_exception(exception)
|
90
|
-
if exception.respond_to?
|
90
|
+
if exception.respond_to?(:original_exception) && exception.original_exception.is_a?(Exception)
|
91
91
|
exception.original_exception
|
92
92
|
else
|
93
93
|
exception
|
@@ -48,23 +48,24 @@ module BetterErrors
|
|
48
48
|
def self.has_binding_stack?(exception)
|
49
49
|
exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
attr_reader :filename, :line, :name, :frame_binding
|
53
|
-
|
53
|
+
|
54
54
|
def initialize(filename, line, name, frame_binding = nil)
|
55
55
|
@filename = filename
|
56
56
|
@line = line
|
57
57
|
@name = name
|
58
58
|
@frame_binding = frame_binding
|
59
|
-
|
59
|
+
|
60
60
|
set_pretty_method_name if frame_binding
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def application?
|
64
|
-
root = BetterErrors.application_root
|
65
|
-
|
64
|
+
if root = BetterErrors.application_root
|
65
|
+
filename.index(root) == 0 && filename.index("#{root}/vendor") != 0
|
66
|
+
end
|
66
67
|
end
|
67
|
-
|
68
|
+
|
68
69
|
def application_path
|
69
70
|
filename[(BetterErrors.application_root.length+1)..-1]
|
70
71
|
end
|
@@ -72,7 +73,7 @@ module BetterErrors
|
|
72
73
|
def gem?
|
73
74
|
Gem.path.any? { |path| filename.index(path) == 0 }
|
74
75
|
end
|
75
|
-
|
76
|
+
|
76
77
|
def gem_path
|
77
78
|
if path = Gem.path.detect { |path| filename.index(path) == 0 }
|
78
79
|
gem_name_and_version, path = filename.sub("#{path}/gems/", "").split("/", 2)
|
@@ -88,7 +89,7 @@ module BetterErrors
|
|
88
89
|
def method_name
|
89
90
|
@method_name || @name
|
90
91
|
end
|
91
|
-
|
92
|
+
|
92
93
|
def context
|
93
94
|
if gem?
|
94
95
|
:gem
|
@@ -98,7 +99,7 @@ module BetterErrors
|
|
98
99
|
:dunno
|
99
100
|
end
|
100
101
|
end
|
101
|
-
|
102
|
+
|
102
103
|
def pretty_path
|
103
104
|
case context
|
104
105
|
when :application; application_path
|
@@ -106,7 +107,7 @@ module BetterErrors
|
|
106
107
|
else filename
|
107
108
|
end
|
108
109
|
end
|
109
|
-
|
110
|
+
|
110
111
|
def local_variables
|
111
112
|
return {} unless frame_binding
|
112
113
|
frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
|
@@ -122,7 +123,7 @@ module BetterErrors
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
end
|
125
|
-
|
126
|
+
|
126
127
|
def instance_variables
|
127
128
|
return {} unless frame_binding
|
128
129
|
Hash[visible_instance_variables.map { |x|
|
@@ -137,7 +138,7 @@ module BetterErrors
|
|
137
138
|
def to_s
|
138
139
|
"#{pretty_path}:#{line}:in `#{name}'"
|
139
140
|
end
|
140
|
-
|
141
|
+
|
141
142
|
private
|
142
143
|
def set_pretty_method_name
|
143
144
|
return if RUBY_VERSION < "2.0.0"
|
@@ -180,6 +180,7 @@
|
|
180
180
|
padding-right: 20px;
|
181
181
|
overflow-y: auto;
|
182
182
|
word-wrap: break-word;
|
183
|
+
white-space: pre-wrap;
|
183
184
|
height: auto;
|
184
185
|
max-height: 7em;
|
185
186
|
}
|
@@ -443,13 +444,13 @@
|
|
443
444
|
font-weight: bold;
|
444
445
|
font-size: 10pt;
|
445
446
|
}
|
446
|
-
|
447
|
+
|
447
448
|
.trace_info .title .location a {
|
448
449
|
color:inherit;
|
449
450
|
text-decoration:none;
|
450
451
|
border-bottom:1px solid #aaaaaa;
|
451
452
|
}
|
452
|
-
|
453
|
+
|
453
454
|
.trace_info .title .location a:hover {
|
454
455
|
border-color:#666666;
|
455
456
|
}
|
@@ -472,7 +473,7 @@
|
|
472
473
|
padding-bottom:9px;
|
473
474
|
float:left;
|
474
475
|
}
|
475
|
-
|
476
|
+
|
476
477
|
.code_linenums span{
|
477
478
|
display:block;
|
478
479
|
padding:0 12px;
|
@@ -768,7 +769,7 @@
|
|
768
769
|
(function() {
|
769
770
|
|
770
771
|
var OID = <%== object_id.to_s.inspect %>;
|
771
|
-
|
772
|
+
|
772
773
|
var previousFrame = null;
|
773
774
|
var previousFrameInfo = null;
|
774
775
|
var allFrames = document.querySelectorAll("ul.frames li");
|
@@ -786,68 +787,73 @@
|
|
786
787
|
}
|
787
788
|
};
|
788
789
|
}
|
789
|
-
|
790
|
+
|
790
791
|
function escapeHTML(html) {
|
791
792
|
return html.replace(/&/, "&").replace(/</g, "<");
|
792
793
|
}
|
793
|
-
|
794
|
+
|
794
795
|
function REPL(index) {
|
795
796
|
this.index = index;
|
796
|
-
|
797
|
-
|
798
|
-
|
797
|
+
|
798
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
799
|
+
if(previousCommands === null) {
|
800
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify([]));
|
801
|
+
previousCommands = [];
|
802
|
+
}
|
803
|
+
|
804
|
+
this.previousCommandOffset = previousCommands.length;
|
799
805
|
}
|
800
|
-
|
806
|
+
|
801
807
|
REPL.all = [];
|
802
|
-
|
808
|
+
|
803
809
|
REPL.prototype.install = function(containerElement) {
|
804
810
|
this.container = containerElement;
|
805
|
-
|
811
|
+
|
806
812
|
this.promptElement = this.container.querySelector(".prompt span");
|
807
813
|
this.inputElement = this.container.querySelector("input");
|
808
814
|
this.outputElement = this.container.querySelector("pre");
|
809
|
-
|
815
|
+
|
810
816
|
var self = this;
|
811
817
|
this.inputElement.onkeydown = function(ev) {
|
812
818
|
self.onKeyDown(ev);
|
813
819
|
};
|
814
|
-
|
820
|
+
|
815
821
|
this.setPrompt(">>");
|
816
|
-
|
822
|
+
|
817
823
|
REPL.all[this.index] = this;
|
818
824
|
}
|
819
|
-
|
825
|
+
|
820
826
|
REPL.prototype.focus = function() {
|
821
827
|
this.inputElement.focus();
|
822
828
|
};
|
823
|
-
|
829
|
+
|
824
830
|
REPL.prototype.setPrompt = function(prompt) {
|
825
831
|
this._prompt = prompt;
|
826
832
|
this.promptElement.innerHTML = escapeHTML(prompt);
|
827
833
|
};
|
828
|
-
|
834
|
+
|
829
835
|
REPL.prototype.getInput = function() {
|
830
836
|
return this.inputElement.value;
|
831
837
|
};
|
832
|
-
|
838
|
+
|
833
839
|
REPL.prototype.setInput = function(text) {
|
834
840
|
this.inputElement.value = text;
|
835
|
-
|
841
|
+
|
836
842
|
if(this.inputElement.setSelectionRange) {
|
837
843
|
// set cursor to end of input
|
838
844
|
this.inputElement.setSelectionRange(text.length, text.length);
|
839
845
|
}
|
840
846
|
};
|
841
|
-
|
847
|
+
|
842
848
|
REPL.prototype.writeRawOutput = function(output) {
|
843
849
|
this.outputElement.innerHTML += output;
|
844
850
|
this.outputElement.scrollTop = this.outputElement.scrollHeight;
|
845
851
|
};
|
846
|
-
|
852
|
+
|
847
853
|
REPL.prototype.writeOutput = function(output) {
|
848
854
|
this.writeRawOutput(escapeHTML(output));
|
849
855
|
};
|
850
|
-
|
856
|
+
|
851
857
|
REPL.prototype.sendInput = function(line) {
|
852
858
|
var self = this;
|
853
859
|
apiCall("eval", { "index": this.index, source: line }, function(response) {
|
@@ -861,48 +867,56 @@
|
|
861
867
|
self.setInput(response.prefilled_input);
|
862
868
|
});
|
863
869
|
};
|
864
|
-
|
870
|
+
|
865
871
|
REPL.prototype.onEnterKey = function() {
|
866
872
|
var text = this.getInput();
|
867
873
|
if(text != "" && text !== undefined) {
|
868
|
-
|
874
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
875
|
+
this.previousCommandOffset = previousCommands.push(text);
|
876
|
+
if(previousCommands.length > 100) {
|
877
|
+
previousCommands.splice(0, 1);
|
878
|
+
}
|
879
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify(previousCommands));
|
869
880
|
}
|
870
881
|
this.setInput("");
|
871
882
|
this.sendInput(text);
|
872
883
|
};
|
873
|
-
|
884
|
+
|
874
885
|
REPL.prototype.onNavigateHistory = function(direction) {
|
875
886
|
this.previousCommandOffset += direction;
|
876
|
-
|
887
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
888
|
+
|
877
889
|
if(this.previousCommandOffset < 0) {
|
878
890
|
this.previousCommandOffset = -1;
|
879
891
|
this.setInput("");
|
880
892
|
return;
|
881
893
|
}
|
882
|
-
|
883
|
-
if(this.previousCommandOffset >=
|
884
|
-
this.previousCommandOffset =
|
894
|
+
|
895
|
+
if(this.previousCommandOffset >= previousCommands.length) {
|
896
|
+
this.previousCommandOffset = previousCommands.length;
|
885
897
|
this.setInput("");
|
886
898
|
return;
|
887
899
|
}
|
888
|
-
|
889
|
-
this.setInput(
|
900
|
+
|
901
|
+
this.setInput(previousCommands[this.previousCommandOffset]);
|
890
902
|
};
|
891
|
-
|
903
|
+
|
892
904
|
REPL.prototype.onKeyDown = function(ev) {
|
893
905
|
if(ev.keyCode == 13) {
|
894
906
|
this.onEnterKey();
|
895
|
-
} else if(ev.keyCode == 38) {
|
896
|
-
// the user pressed the up arrow
|
907
|
+
} else if(ev.keyCode == 38 || (ev.ctrlKey && ev.keyCode == 80)) {
|
908
|
+
// the user pressed the up arrow or Ctrl-P
|
897
909
|
this.onNavigateHistory(-1);
|
910
|
+
ev.preventDefault();
|
898
911
|
return false;
|
899
|
-
} else if(ev.keyCode == 40) {
|
900
|
-
// the user pressed the down arrow
|
912
|
+
} else if(ev.keyCode == 40 || (ev.ctrlKey && ev.keyCode == 78)) {
|
913
|
+
// the user pressed the down arrow or Ctrl-N
|
901
914
|
this.onNavigateHistory(1);
|
915
|
+
ev.preventDefault();
|
902
916
|
return false;
|
903
917
|
}
|
904
918
|
};
|
905
|
-
|
919
|
+
|
906
920
|
function switchTo(el) {
|
907
921
|
if(previousFrameInfo) previousFrameInfo.style.display = "none";
|
908
922
|
previousFrameInfo = el;
|
@@ -937,7 +951,7 @@
|
|
937
951
|
});
|
938
952
|
}
|
939
953
|
}
|
940
|
-
|
954
|
+
|
941
955
|
for(var i = 0; i < allFrames.length; i++) {
|
942
956
|
(function(i, el) {
|
943
957
|
var el = allFrames[i];
|
@@ -947,12 +961,12 @@
|
|
947
961
|
}
|
948
962
|
el.className = "selected";
|
949
963
|
previousFrame = el;
|
950
|
-
|
964
|
+
|
951
965
|
selectFrameInfo(el.attributes["data-index"].value);
|
952
966
|
};
|
953
967
|
})(i);
|
954
968
|
}
|
955
|
-
|
969
|
+
|
956
970
|
// Click the first application frame
|
957
971
|
(
|
958
972
|
document.querySelector(".frames li.application") ||
|
@@ -968,7 +982,7 @@
|
|
968
982
|
var applicationFramesButtonIsInstalled = false;
|
969
983
|
var applicationFramesButton = document.getElementById("application_frames");
|
970
984
|
var allFramesButton = document.getElementById("all_frames");
|
971
|
-
|
985
|
+
|
972
986
|
// The application frames button only needs to be bound if
|
973
987
|
// there are actually any application frames to look at.
|
974
988
|
var installApplicationFramesButton = function() {
|
@@ -984,10 +998,10 @@
|
|
984
998
|
}
|
985
999
|
return false;
|
986
1000
|
};
|
987
|
-
|
1001
|
+
|
988
1002
|
applicationFramesButtonIsInstalled = true;
|
989
1003
|
}
|
990
|
-
|
1004
|
+
|
991
1005
|
allFramesButton.onclick = function() {
|
992
1006
|
if(applicationFramesButtonIsInstalled) {
|
993
1007
|
applicationFramesButton.className = "";
|
@@ -999,7 +1013,7 @@
|
|
999
1013
|
}
|
1000
1014
|
return false;
|
1001
1015
|
};
|
1002
|
-
|
1016
|
+
|
1003
1017
|
// If there are no application frames, select the 'All Frames'
|
1004
1018
|
// tab by default.
|
1005
1019
|
if(applicationFramesCount > 0) {
|
@@ -71,6 +71,40 @@ module BetterErrors
|
|
71
71
|
status.should == 500
|
72
72
|
end
|
73
73
|
|
74
|
+
context "original_exception" do
|
75
|
+
class OriginalExceptionException < Exception
|
76
|
+
attr_reader :original_exception
|
77
|
+
|
78
|
+
def initialize(message, original_exception = nil)
|
79
|
+
super(message)
|
80
|
+
@original_exception = original_exception
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "shows Original Exception if it responds_to and has an original_exception" do
|
85
|
+
app = Middleware.new(->env {
|
86
|
+
raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception"))
|
87
|
+
})
|
88
|
+
|
89
|
+
status, _, body = app.call({})
|
90
|
+
|
91
|
+
status.should == 500
|
92
|
+
body.join.should_not match(/Other Exception/)
|
93
|
+
body.join.should match(/Original Exception/)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "won't crash if the exception responds_to but doesn't have an original_exception" do
|
97
|
+
app = Middleware.new(->env {
|
98
|
+
raise OriginalExceptionException.new("Other Exception")
|
99
|
+
})
|
100
|
+
|
101
|
+
status, _, body = app.call({})
|
102
|
+
|
103
|
+
status.should == 500
|
104
|
+
body.join.should match(/Other Exception/)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
74
108
|
it "returns ExceptionWrapper's status_code" do
|
75
109
|
ad_ew = double("ActionDispatch::ExceptionWrapper")
|
76
110
|
ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) }
|
@@ -25,7 +25,11 @@ module BetterErrors
|
|
25
25
|
filled.should == " "
|
26
26
|
|
27
27
|
output, prompt, filled = repl.send_input "end"
|
28
|
-
|
28
|
+
if RUBY_VERSION >= "2.1.0"
|
29
|
+
output.should == "=> :f\n"
|
30
|
+
else
|
31
|
+
output.should == "=> nil\n"
|
32
|
+
end
|
29
33
|
prompt.should == ">>"
|
30
34
|
filled.should == ""
|
31
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_errors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charlie Somerville
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: erubis
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- .gitignore
|
51
51
|
- .travis.yml
|
52
52
|
- .yardopts
|
53
|
+
- CHANGELOG.md
|
53
54
|
- Gemfile
|
54
55
|
- LICENSE.txt
|
55
56
|
- README.md
|