better_errors 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
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
|