better_errors 2.5.1 → 2.9.1

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +130 -0
  3. data/.github/workflows/release.yml +64 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +6 -1
  6. data/README.md +34 -2
  7. data/better_errors.gemspec +3 -1
  8. data/gemfiles/pry010.gemfile +2 -1
  9. data/gemfiles/pry011.gemfile +2 -1
  10. data/gemfiles/pry09.gemfile +2 -1
  11. data/gemfiles/rack.gemfile +2 -1
  12. data/gemfiles/rack_boc.gemfile +2 -1
  13. data/gemfiles/rails42.gemfile +3 -1
  14. data/gemfiles/rails42_boc.gemfile +3 -1
  15. data/gemfiles/rails42_haml.gemfile +3 -1
  16. data/gemfiles/rails50.gemfile +3 -1
  17. data/gemfiles/rails50_boc.gemfile +3 -1
  18. data/gemfiles/rails50_haml.gemfile +3 -1
  19. data/gemfiles/rails51.gemfile +3 -1
  20. data/gemfiles/rails51_boc.gemfile +3 -1
  21. data/gemfiles/rails51_haml.gemfile +3 -1
  22. data/gemfiles/rails52.gemfile +3 -1
  23. data/gemfiles/rails52_boc.gemfile +3 -1
  24. data/gemfiles/rails52_haml.gemfile +3 -1
  25. data/gemfiles/rails60.gemfile +8 -0
  26. data/gemfiles/rails60_boc.gemfile +9 -0
  27. data/gemfiles/rails60_haml.gemfile +9 -0
  28. data/lib/better_errors.rb +20 -33
  29. data/lib/better_errors/editor.rb +99 -0
  30. data/lib/better_errors/error_page.rb +31 -4
  31. data/lib/better_errors/exception_hint.rb +29 -0
  32. data/lib/better_errors/middleware.rb +59 -12
  33. data/lib/better_errors/raised_exception.rb +25 -4
  34. data/lib/better_errors/stack_frame.rb +8 -2
  35. data/lib/better_errors/templates/main.erb +61 -17
  36. data/lib/better_errors/templates/text.erb +5 -2
  37. data/lib/better_errors/templates/variable_info.erb +9 -2
  38. data/lib/better_errors/version.rb +1 -1
  39. metadata +28 -7
  40. data/.travis.yml +0 -62
@@ -1,12 +1,23 @@
1
+ require 'better_errors/exception_hint'
2
+
1
3
  # @private
2
4
  module BetterErrors
3
5
  class RaisedException
4
- attr_reader :exception, :message, :backtrace
6
+ attr_reader :exception, :message, :backtrace, :hint
5
7
 
6
8
  def initialize(exception)
7
- if exception.respond_to?(:cause)
9
+ if exception.class.name == "ActionView::Template::Error" && exception.respond_to?(:cause)
10
+ # Rails 6+ exceptions of this type wrap the "real" exception, and the real exception
11
+ # is actually more useful than the ActionView-provided wrapper. Once Better Errors
12
+ # supports showing all exceptions in the cause stack, this should go away. Or perhaps
13
+ # this can be changed to provide guidance by showing the second error in the cause stack
14
+ # under this condition.
8
15
  exception = exception.cause if exception.cause
9
16
  elsif exception.respond_to?(:original_exception) && exception.original_exception
17
+ # This supports some specific Rails exceptions, and this is not intended to act the same as
18
+ # the Ruby's {Exception#cause}.
19
+ # It's possible this should only support ActionView::Template::Error, but by not changing
20
+ # this we're preserving longstanding behavior of Better Errors with Rails < 6.
10
21
  exception = exception.original_exception
11
22
  end
12
23
 
@@ -14,6 +25,7 @@ module BetterErrors
14
25
  @message = exception.message
15
26
 
16
27
  setup_backtrace
28
+ setup_hint
17
29
  massage_syntax_error
18
30
  end
19
31
 
@@ -36,8 +48,13 @@ module BetterErrors
36
48
 
37
49
  def setup_backtrace_from_bindings
38
50
  @backtrace = exception.__better_errors_bindings_stack.map { |binding|
39
- file = binding.eval "__FILE__"
40
- line = binding.eval "__LINE__"
51
+ if binding.respond_to?(:source_location) # Ruby >= 2.6
52
+ file = binding.source_location[0]
53
+ line = binding.source_location[1]
54
+ else
55
+ file = binding.eval "__FILE__"
56
+ line = binding.eval "__LINE__"
57
+ end
41
58
  name = binding.frame_description
42
59
  StackFrame.new(file, line, name, binding)
43
60
  }
@@ -64,5 +81,9 @@ module BetterErrors
64
81
  end
65
82
  end
66
83
  end
84
+
85
+ def setup_hint
86
+ @hint = ExceptionHint.new(exception).hint
87
+ end
67
88
  end
68
89
  end
@@ -69,7 +69,10 @@ module BetterErrors
69
69
  def local_variables
70
70
  return {} unless frame_binding
71
71
 
72
- frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
72
+ lv = frame_binding.eval("local_variables")
73
+ return {} unless lv
74
+
75
+ lv.each_with_object({}) do |name, hash|
73
76
  # Ruby 2.2's local_variables will include the hidden #$! variable if
74
77
  # called from within a rescue context. This is not a valid variable name,
75
78
  # so the local_variable_get method complains. This should probably be
@@ -94,7 +97,10 @@ module BetterErrors
94
97
  end
95
98
 
96
99
  def visible_instance_variables
97
- frame_binding.eval("instance_variables") - BetterErrors.ignored_instance_variables
100
+ iv = frame_binding.eval("instance_variables")
101
+ return {} unless iv
102
+
103
+ iv - BetterErrors.ignored_instance_variables
98
104
  end
99
105
 
100
106
  def to_s
@@ -90,7 +90,7 @@
90
90
  nav.sidebar,
91
91
  .frame_info {
92
92
  position: fixed;
93
- top: 95px;
93
+ top: 102px;
94
94
  bottom: 0;
95
95
 
96
96
  box-sizing: border-box;
@@ -102,7 +102,7 @@
102
102
  nav.sidebar {
103
103
  width: 40%;
104
104
  left: 20px;
105
- top: 115px;
105
+ top: 122px;
106
106
  bottom: 20px;
107
107
  }
108
108
 
@@ -131,7 +131,7 @@
131
131
  header.exception {
132
132
  padding: 18px 20px;
133
133
 
134
- height: 59px;
134
+ height: 66px;
135
135
  min-height: 59px;
136
136
 
137
137
  overflow: hidden;
@@ -146,6 +146,14 @@
146
146
  }
147
147
 
148
148
  /* Heading */
149
+ header.exception .fix-actions {
150
+ margin-top: .5em;
151
+ }
152
+
153
+ header.exception .fix-actions input[type=submit] {
154
+ font-weight: bold;
155
+ }
156
+
149
157
  header.exception h2 {
150
158
  font-weight: 200;
151
159
  font-size: 11pt;
@@ -153,7 +161,7 @@
153
161
 
154
162
  header.exception h2,
155
163
  header.exception p {
156
- line-height: 1.4em;
164
+ line-height: 1.5em;
157
165
  overflow: hidden;
158
166
  white-space: pre;
159
167
  text-overflow: ellipsis;
@@ -166,7 +174,7 @@
166
174
 
167
175
  header.exception p {
168
176
  font-weight: 200;
169
- font-size: 20pt;
177
+ font-size: 17pt;
170
178
  color: white;
171
179
  }
172
180
 
@@ -587,6 +595,9 @@
587
595
  color: #8080a0;
588
596
  padding-left: 20px;
589
597
  }
598
+ .console-has-been-used .live-console-hint {
599
+ display: none;
600
+ }
590
601
 
591
602
  .hint:before {
592
603
  content: '\25b2';
@@ -603,17 +614,6 @@
603
614
  margin: 10px 0;
604
615
  }
605
616
 
606
- .sub:before {
607
- content: '';
608
- display: block;
609
- width: 100%;
610
- height: 4px;
611
-
612
- border-radius: 2px;
613
- background: rgba(0, 150, 200, 0.05);
614
- 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);
615
- }
616
-
617
617
  .sub h3 {
618
618
  color: #39a;
619
619
  font-size: 1.1em;
@@ -744,6 +744,21 @@
744
744
  <header class="exception">
745
745
  <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
746
746
  <p><%= exception_message %></p>
747
+ <% unless active_support_actions.empty? %>
748
+ <div class='fix-actions'>
749
+ <% active_support_actions.each do |action, _| %>
750
+ <form class="button_to" method="post" action="<%= action_dispatch_action_endpoint %>">
751
+ <input type="submit" value="<%= action %>">
752
+ <input type="hidden" name="action" value="<%= action %>">
753
+ <input type="hidden" name="error" value="<%= exception_type %>">
754
+ <input type="hidden" name="location" value="<%= request_path %>">
755
+ </form>
756
+ <% end %>
757
+ </div>
758
+ <% end %>
759
+ <% if exception_hint %>
760
+ <h2>Hint: <%= exception_hint %></h2>
761
+ <% end %>
747
762
  </header>
748
763
  </div>
749
764
 
@@ -780,6 +795,7 @@
780
795
  (function() {
781
796
 
782
797
  var OID = "<%= id %>";
798
+ var csrfToken = "<%= csrf_token %>";
783
799
 
784
800
  var previousFrame = null;
785
801
  var previousFrameInfo = null;
@@ -790,6 +806,7 @@
790
806
  var req = new XMLHttpRequest();
791
807
  req.open("POST", "//" + window.location.host + <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
792
808
  req.setRequestHeader("Content-Type", "application/json");
809
+ opts.csrfToken = csrfToken;
793
810
  req.send(JSON.stringify(opts));
794
811
  req.onreadystatechange = function() {
795
812
  if(req.readyState == 4) {
@@ -803,6 +820,28 @@
803
820
  return html.replace(/&/, "&amp;").replace(/</g, "&lt;");
804
821
  }
805
822
 
823
+ function hasConsoleBeenUsedPreviously() {
824
+ return !!document.cookie.split('; ').find(function(cookie) {
825
+ return cookie.startsWith('BetterErrors-has-used-console=');
826
+ });
827
+ }
828
+
829
+ var consoleHasBeenUsed = hasConsoleBeenUsedPreviously();
830
+
831
+ function consoleWasJustUsed() {
832
+ if (consoleHasBeenUsed) {
833
+ return;
834
+ }
835
+
836
+ hideConsoleHint();
837
+ consoleHasBeenUsed = true;
838
+ document.cookie = "BetterErrors-has-used-console=true;path=/;max-age=31536000;samesite"
839
+ }
840
+
841
+ function hideConsoleHint() {
842
+ document.querySelector('body').className += " console-has-been-used";
843
+ }
844
+
806
845
  function REPL(index) {
807
846
  this.index = index;
808
847
 
@@ -824,15 +863,20 @@
824
863
  this.inputElement = this.container.querySelector("input");
825
864
  this.outputElement = this.container.querySelector("pre");
826
865
 
866
+ if (consoleHasBeenUsed) {
867
+ hideConsoleHint();
868
+ }
869
+
827
870
  var self = this;
828
871
  this.inputElement.onkeydown = function(ev) {
829
872
  self.onKeyDown(ev);
873
+ consoleWasJustUsed();
830
874
  };
831
875
 
832
876
  this.setPrompt(">>");
833
877
 
834
878
  REPL.all[this.index] = this;
835
- }
879
+ };
836
880
 
837
881
  REPL.prototype.focus = function() {
838
882
  this.inputElement.focus();
@@ -1,7 +1,10 @@
1
1
  <%== text_heading("=", "%s at %s" % [exception_type, request_path]) %>
2
2
 
3
- > <%== exception_message %>
4
- <% if backtrace_frames.any? %>
3
+ <%== exception_message %>
4
+
5
+ > To access an interactive console with this error, point your browser to: /__better_errors
6
+
7
+ <% if backtrace_frames.any? -%>
5
8
 
6
9
  <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
7
10
 
@@ -1,7 +1,14 @@
1
1
  <header class="trace_info clearfix">
2
2
  <div class="title">
3
3
  <h2 class="name"><%= @frame.name %></h2>
4
- <div class="location"><span class="filename"><a href="<%= editor_url(@frame) %>"><%= @frame.pretty_path %></a></span></div>
4
+ <div class="location">
5
+ <span class="filename">
6
+ <a
7
+ href="<%= editor_url(@frame) %>"
8
+ <%= ENV.key?('BETTER_ERRORS_INSIDE_FRAME') ? "target=_blank" : '' %>
9
+ ><%= @frame.pretty_path %></a>
10
+ </span>
11
+ </div>
5
12
  </div>
6
13
  <div class="code_block clearfix">
7
14
  <%== html_formatted_code_block @frame %>
@@ -18,7 +25,7 @@
18
25
  </header>
19
26
 
20
27
  <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
21
- <div class="hint">
28
+ <div class="hint live-console-hint">
22
29
  This is a live shell. Type in here.
23
30
  </div>
24
31
 
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.5.1"
2
+ VERSION = "2.9.1"
3
3
  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: 2.5.1
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2020-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec-its
42
+ name: rspec-html-matchers
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: yard
56
+ name: rspec-its
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: kramdown
70
+ name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: kramdown
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: erubi
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -132,8 +146,10 @@ extensions: []
132
146
  extra_rdoc_files: []
133
147
  files:
134
148
  - ".coveralls.yml"
149
+ - ".github/workflows/ci.yml"
150
+ - ".github/workflows/release.yml"
135
151
  - ".gitignore"
136
- - ".travis.yml"
152
+ - ".ruby-version"
137
153
  - ".yardopts"
138
154
  - CHANGELOG.md
139
155
  - Gemfile
@@ -157,12 +173,17 @@ files:
157
173
  - gemfiles/rails52.gemfile
158
174
  - gemfiles/rails52_boc.gemfile
159
175
  - gemfiles/rails52_haml.gemfile
176
+ - gemfiles/rails60.gemfile
177
+ - gemfiles/rails60_boc.gemfile
178
+ - gemfiles/rails60_haml.gemfile
160
179
  - lib/better_errors.rb
161
180
  - lib/better_errors/code_formatter.rb
162
181
  - lib/better_errors/code_formatter/html.rb
163
182
  - lib/better_errors/code_formatter/text.rb
183
+ - lib/better_errors/editor.rb
164
184
  - lib/better_errors/error_page.rb
165
185
  - lib/better_errors/exception_extension.rb
186
+ - lib/better_errors/exception_hint.rb
166
187
  - lib/better_errors/inspectable_value.rb
167
188
  - lib/better_errors/middleware.rb
168
189
  - lib/better_errors/rails.rb
@@ -197,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
218
  - !ruby/object:Gem::Version
198
219
  version: '0'
199
220
  requirements: []
200
- rubygems_version: 3.0.1
221
+ rubygems_version: 3.1.4
201
222
  signing_key:
202
223
  specification_version: 4
203
224
  summary: Better error page for Rails and other Rack apps
@@ -1,62 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- cache: bundler
4
- before_install:
5
- # Since Rails 4.2 only supports rubygems < 2, we must install an older version for it.
6
- - >
7
- if [[ "$BUNDLE_GEMFILE" =~ "rails42" ]]; then
8
- rvm @global do gem install rubygems-update -v '<2'
9
- update_rubygems
10
- rvm @global do gem uninstall bundler --force --executables
11
- rvm @global do gem install bundler -v "~> 1.3"
12
- fi
13
-
14
- notifications:
15
- webhooks:
16
- # With COVERALLS_PARALLEL, coverage information sent to coveralls will not be processed until
17
- # this webhook is sent.
18
- # https://coveralls.zendesk.com/hc/en-us/articles/203484329-Parallel-Build-Webhook
19
- - secure: "YnHYbTq51ySistjvOxsuNhyg4GLuUffEJstTYeGYXiBF7HG5h43IVYo8KNuLzwkgsOYBcNo+YMdQX7qCqJffSbhsr1FZRSzBmjFFxcyD4hu+ukM2theZ4mePVAZiePscYvQPRNY4hIb4d3egStJEytkalDhB3sOebF57tIaCssg="
20
- rvm:
21
- - 2.2.10
22
- - 2.3.7
23
- - 2.4.4
24
- - 2.5.1
25
- - ruby-head
26
- gemfile:
27
- - gemfiles/rails42.gemfile
28
- - gemfiles/rails50.gemfile
29
- - gemfiles/rails51.gemfile
30
- - gemfiles/rails52.gemfile
31
- - gemfiles/rails42_haml.gemfile
32
- - gemfiles/rails50_haml.gemfile
33
- - gemfiles/rails51_haml.gemfile
34
- - gemfiles/rails52_haml.gemfile
35
- - gemfiles/rails42_boc.gemfile
36
- - gemfiles/rails50_boc.gemfile
37
- - gemfiles/rails51_boc.gemfile
38
- - gemfiles/rails52_boc.gemfile
39
- - gemfiles/rack.gemfile
40
- - gemfiles/rack_boc.gemfile
41
- - gemfiles/pry09.gemfile
42
- - gemfiles/pry010.gemfile
43
- - gemfiles/pry011.gemfile
44
- matrix:
45
- fast_finish: true
46
- allow_failures:
47
- - rvm: ruby-head
48
- - gemfile: gemfiles/pry010.gemfile
49
- - gemfile: gemfiles/pry011.gemfile
50
- exclude:
51
- - rvm: 2.4.4
52
- gemfile: gemfiles/rails42.gemfile
53
- - rvm: 2.4.4
54
- gemfile: gemfiles/rails42_boc.gemfile
55
- - rvm: 2.4.4
56
- gemfile: gemfiles/rails42_haml.gemfile
57
- - rvm: 2.5.1
58
- gemfile: gemfiles/rails42.gemfile
59
- - rvm: 2.5.1
60
- gemfile: gemfiles/rails42_boc.gemfile
61
- - rvm: 2.5.1
62
- gemfile: gemfiles/rails42_haml.gemfile