better_errors 1.0.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.gitignore +7 -5
- data/.travis.yml +1 -3
- data/CHANGELOG.md +3 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +12 -2
- data/Rakefile +12 -3
- data/better_errors.gemspec +3 -4
- data/lib/better_errors/error_page.rb +22 -33
- data/lib/better_errors/exception_extension.rb +17 -0
- data/lib/better_errors/middleware.rb +7 -7
- data/lib/better_errors/raised_exception.rb +66 -0
- data/lib/better_errors/repl/pry.rb +2 -2
- data/lib/better_errors/stack_frame.rb +19 -67
- data/lib/better_errors/templates/main.erb +63 -49
- data/lib/better_errors/templates/text.erb +2 -2
- data/lib/better_errors/version.rb +1 -1
- data/lib/better_errors.rb +7 -8
- data/spec/better_errors/middleware_spec.rb +42 -0
- data/spec/better_errors/raised_exception_spec.rb +52 -0
- data/spec/better_errors/repl/pry_spec.rb +5 -1
- data/spec/better_errors/stack_frame_spec.rb +26 -30
- data/spec/spec_helper.rb +2 -4
- data/spec/without_binding_of_caller.rb +9 -0
- metadata +35 -18
- data/ext/mkrf_conf.rb +0 -11
- data/lib/better_errors/core_ext/exception.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bc36d3113c7041816a7697fbd1e50333f5976003
|
|
4
|
+
data.tar.gz: 834f3f4a4903a45f150d83adde3f25452d2fd86b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 130d61a4ce2e5509eb1585dfa0e3c620bf54387ac6a0931d1a534296460a0e06601a6d71ce41b3d3ffbd15951626ddfd7e753bb1bc911c35cf76cfa52cfcd771
|
|
7
|
+
data.tar.gz: 5906697a352187036b92cdefe124fea459405d7e3cc80f3bcc6f07c7a2952f328367f452e88272947edef464a4cc75fbe3d276c24580b9b633b6f9e60c99a60d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Better Errors [](https://rubygems.org/gems/better_errors) [](https://travis-ci.org/charliesome/better_errors) [](https://codeclimate.com/github/charliesome/better_errors)
|
|
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
|
|
|
@@ -21,6 +21,16 @@ group :development do
|
|
|
21
21
|
end
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
If you would like to use Better Errors' **advanced features** (REPL, local/instance variable inspection, pretty stack frame names), you need to add the [`binding_of_caller`](https://github.com/banister/binding_of_caller) gem by [@banisterfiend](http://twitter.com/banisterfiend) to your Gemfile:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem "binding_of_caller"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This is an optional dependency however, and Better Errors will work without it.
|
|
31
|
+
|
|
32
|
+
_Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._
|
|
33
|
+
|
|
24
34
|
## Security
|
|
25
35
|
|
|
26
36
|
**NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.**
|
data/Rakefile
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
require "bundler/gem_tasks"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
require "rspec/core/rake_task"
|
|
3
|
+
|
|
4
|
+
namespace :test do
|
|
5
|
+
RSpec::Core::RakeTask.new(:with_binding_of_caller)
|
|
6
|
+
|
|
7
|
+
without_task = RSpec::Core::RakeTask.new(:without_binding_of_caller)
|
|
8
|
+
without_task.ruby_opts = "-I spec -r without_binding_of_caller"
|
|
9
|
+
|
|
10
|
+
task :all => [:with_binding_of_caller, :without_binding_of_caller]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task :default => "test:all"
|
data/better_errors.gemspec
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
3
|
require 'better_errors/version'
|
|
@@ -16,12 +15,12 @@ Gem::Specification.new do |s|
|
|
|
16
15
|
s.files = `git ls-files`.split($/)
|
|
17
16
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
18
17
|
s.require_paths = ["lib"]
|
|
19
|
-
s.extensions = ["ext/mkrf_conf.rb"]
|
|
20
18
|
|
|
21
|
-
s.required_ruby_version = ">=
|
|
22
|
-
|
|
19
|
+
s.required_ruby_version = ">= 2.0.0"
|
|
20
|
+
|
|
23
21
|
s.add_dependency "erubis", ">= 2.6.6"
|
|
24
22
|
s.add_dependency "coderay", ">= 1.0.0"
|
|
23
|
+
s.add_dependency "rack", ">= 0.9.0"
|
|
25
24
|
|
|
26
25
|
# optional dependencies:
|
|
27
26
|
# s.add_dependency "binding_of_caller"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "cgi"
|
|
2
2
|
require "json"
|
|
3
|
+
require "securerandom"
|
|
3
4
|
|
|
4
5
|
module BetterErrors
|
|
5
6
|
# @private
|
|
@@ -7,42 +8,46 @@ module BetterErrors
|
|
|
7
8
|
def self.template_path(template_name)
|
|
8
9
|
File.expand_path("../templates/#{template_name}.erb", __FILE__)
|
|
9
10
|
end
|
|
10
|
-
|
|
11
|
+
|
|
11
12
|
def self.template(template_name)
|
|
12
13
|
Erubis::EscapedEruby.new(File.read(template_path(template_name)))
|
|
13
14
|
end
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
attr_reader :exception, :env, :repls
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
def initialize(exception, env)
|
|
18
|
-
@exception =
|
|
19
|
+
@exception = RaisedException.new(exception)
|
|
19
20
|
@env = env
|
|
20
21
|
@start_time = Time.now.to_f
|
|
21
22
|
@repls = []
|
|
22
23
|
end
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
def id
|
|
26
|
+
@id ||= SecureRandom.hex(8)
|
|
27
|
+
end
|
|
28
|
+
|
|
24
29
|
def render(template_name = "main")
|
|
25
30
|
self.class.template(template_name).result binding
|
|
26
31
|
end
|
|
27
|
-
|
|
32
|
+
|
|
28
33
|
def do_variables(opts)
|
|
29
34
|
index = opts["index"].to_i
|
|
30
35
|
@frame = backtrace_frames[index]
|
|
31
36
|
@var_start_time = Time.now.to_f
|
|
32
37
|
{ html: render("variable_info") }
|
|
33
38
|
end
|
|
34
|
-
|
|
39
|
+
|
|
35
40
|
def do_eval(opts)
|
|
36
41
|
index = opts["index"].to_i
|
|
37
42
|
code = opts["source"]
|
|
38
|
-
|
|
43
|
+
|
|
39
44
|
unless binding = backtrace_frames[index].frame_binding
|
|
40
45
|
return { error: "REPL unavailable in this stack frame" }
|
|
41
46
|
end
|
|
42
|
-
|
|
47
|
+
|
|
43
48
|
result, prompt, prefilled_input =
|
|
44
49
|
(@repls[index] ||= REPL.provider.new(binding)).send_input(code)
|
|
45
|
-
|
|
50
|
+
|
|
46
51
|
{ result: result,
|
|
47
52
|
prompt: prompt,
|
|
48
53
|
prefilled_input: prefilled_input,
|
|
@@ -50,22 +55,22 @@ module BetterErrors
|
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
def backtrace_frames
|
|
53
|
-
|
|
58
|
+
exception.backtrace
|
|
54
59
|
end
|
|
55
60
|
|
|
56
61
|
def application_frames
|
|
57
|
-
backtrace_frames.select
|
|
62
|
+
backtrace_frames.select(&:application?)
|
|
58
63
|
end
|
|
59
64
|
|
|
60
65
|
def first_frame
|
|
61
|
-
|
|
66
|
+
application_frames.first || backtrace_frames.first
|
|
62
67
|
end
|
|
63
|
-
|
|
68
|
+
|
|
64
69
|
private
|
|
65
70
|
def editor_url(frame)
|
|
66
71
|
BetterErrors.editor[frame.filename, frame.line]
|
|
67
72
|
end
|
|
68
|
-
|
|
73
|
+
|
|
69
74
|
def rack_session
|
|
70
75
|
env['rack.session']
|
|
71
76
|
end
|
|
@@ -77,31 +82,15 @@ module BetterErrors
|
|
|
77
82
|
def uri_prefix
|
|
78
83
|
env["SCRIPT_NAME"] || ""
|
|
79
84
|
end
|
|
80
|
-
|
|
81
|
-
def exception_message
|
|
82
|
-
if exception.is_a?(SyntaxError) && exception.message =~ /\A.*:\d*: (.*)$/
|
|
83
|
-
$1
|
|
84
|
-
else
|
|
85
|
-
exception.message
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
85
|
|
|
89
|
-
def real_exception(exception)
|
|
90
|
-
if exception.respond_to? :original_exception
|
|
91
|
-
exception.original_exception
|
|
92
|
-
else
|
|
93
|
-
exception
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
86
|
def request_path
|
|
98
87
|
env["PATH_INFO"]
|
|
99
88
|
end
|
|
100
|
-
|
|
89
|
+
|
|
101
90
|
def html_formatted_code_block(frame)
|
|
102
91
|
CodeFormatter::HTML.new(frame.filename, frame.line).output
|
|
103
92
|
end
|
|
104
|
-
|
|
93
|
+
|
|
105
94
|
def text_formatted_code_block(frame)
|
|
106
95
|
CodeFormatter::Text.new(frame.filename, frame.line).output
|
|
107
96
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module BetterErrors
|
|
2
|
+
module ExceptionExtension
|
|
3
|
+
prepend_features Exception
|
|
4
|
+
|
|
5
|
+
def set_backtrace(*)
|
|
6
|
+
if caller_locations.none? { |loc| loc.path == __FILE__ }
|
|
7
|
+
@__better_errors_bindings_stack = ::Kernel.binding.callers.drop(1)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def __better_errors_bindings_stack
|
|
14
|
+
@__better_errors_bindings_stack || []
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
require "ipaddr"
|
|
3
3
|
require "set"
|
|
4
|
+
require "rack"
|
|
4
5
|
|
|
5
6
|
module BetterErrors
|
|
6
7
|
# Better Errors' error handling middleware. Including this in your middleware
|
|
@@ -62,16 +63,15 @@ module BetterErrors
|
|
|
62
63
|
private
|
|
63
64
|
|
|
64
65
|
def allow_ip?(env)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
ip = IPAddr.new env["REMOTE_ADDR"].split("%").first
|
|
66
|
+
request = Rack::Request.new(env)
|
|
67
|
+
return true unless request.ip and !request.ip.strip.empty?
|
|
68
|
+
ip = IPAddr.new request.ip.split("%").first
|
|
69
69
|
ALLOWED_IPS.any? { |subnet| subnet.include? ip }
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def better_errors_call(env)
|
|
73
73
|
case env["PATH_INFO"]
|
|
74
|
-
when %r{/__better_errors/(?<
|
|
74
|
+
when %r{/__better_errors/(?<id>.+?)/(?<method>\w+)\z}
|
|
75
75
|
internal_call env, $~
|
|
76
76
|
when %r{/__better_errors/?\z}
|
|
77
77
|
show_error_page env
|
|
@@ -115,7 +115,7 @@ module BetterErrors
|
|
|
115
115
|
def log_exception
|
|
116
116
|
return unless BetterErrors.logger
|
|
117
117
|
|
|
118
|
-
message = "\n#{@error_page.exception.
|
|
118
|
+
message = "\n#{@error_page.exception.type} - #{@error_page.exception.message}:\n"
|
|
119
119
|
@error_page.backtrace_frames.each do |frame|
|
|
120
120
|
message << " #{frame}\n"
|
|
121
121
|
end
|
|
@@ -124,7 +124,7 @@ module BetterErrors
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def internal_call(env, opts)
|
|
127
|
-
if opts[:
|
|
127
|
+
if opts[:id] != @error_page.id
|
|
128
128
|
return [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(error: "Session expired")]]
|
|
129
129
|
end
|
|
130
130
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# @private
|
|
2
|
+
module BetterErrors
|
|
3
|
+
class RaisedException
|
|
4
|
+
attr_reader :exception, :message, :backtrace
|
|
5
|
+
|
|
6
|
+
def initialize(exception)
|
|
7
|
+
if exception.respond_to?(:original_exception) && exception.original_exception
|
|
8
|
+
exception = exception.original_exception
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
@exception = exception
|
|
12
|
+
@message = exception.message
|
|
13
|
+
|
|
14
|
+
setup_backtrace
|
|
15
|
+
massage_syntax_error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def type
|
|
19
|
+
exception.class
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
def has_bindings?
|
|
24
|
+
exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def setup_backtrace
|
|
28
|
+
if has_bindings?
|
|
29
|
+
setup_backtrace_from_bindings
|
|
30
|
+
else
|
|
31
|
+
setup_backtrace_from_backtrace
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup_backtrace_from_bindings
|
|
36
|
+
@backtrace = exception.__better_errors_bindings_stack.map { |binding|
|
|
37
|
+
file = binding.eval "__FILE__"
|
|
38
|
+
line = binding.eval "__LINE__"
|
|
39
|
+
name = binding.frame_description
|
|
40
|
+
StackFrame.new(file, line, name, binding)
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def setup_backtrace_from_backtrace
|
|
45
|
+
@backtrace = (exception.backtrace || []).map { |frame|
|
|
46
|
+
if /\A(?<file>.*?):(?<line>\d+)(:in `(?<name>.*)')?/ =~ frame
|
|
47
|
+
StackFrame.new(file, line.to_i, name)
|
|
48
|
+
end
|
|
49
|
+
}.compact
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def massage_syntax_error
|
|
53
|
+
case exception.class.to_s
|
|
54
|
+
when "Haml::SyntaxError"
|
|
55
|
+
if /\A(.+?):(\d+)/ =~ exception.backtrace.first
|
|
56
|
+
backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
|
|
57
|
+
end
|
|
58
|
+
when "SyntaxError"
|
|
59
|
+
if /\A(.+?):(\d+): (.*)/m =~ exception.message
|
|
60
|
+
backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
|
|
61
|
+
@message = $3
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -36,8 +36,8 @@ module BetterErrors
|
|
|
36
36
|
@fiber = Fiber.new do
|
|
37
37
|
@pry.repl binding
|
|
38
38
|
end
|
|
39
|
-
@input = Input.new
|
|
40
|
-
@output = Output.new
|
|
39
|
+
@input = BetterErrors::REPL::Pry::Input.new
|
|
40
|
+
@output = BetterErrors::REPL::Pry::Output.new
|
|
41
41
|
@pry = ::Pry.new input: @input, output: @output
|
|
42
42
|
@pry.hooks.clear_all if defined?(@pry.hooks.clear_all)
|
|
43
43
|
@fiber.resume
|
|
@@ -4,67 +4,26 @@ module BetterErrors
|
|
|
4
4
|
# @private
|
|
5
5
|
class StackFrame
|
|
6
6
|
def self.from_exception(exception)
|
|
7
|
-
|
|
8
|
-
list = exception.__better_errors_bindings_stack.map { |binding|
|
|
9
|
-
file = binding.eval "__FILE__"
|
|
10
|
-
line = binding.eval "__LINE__"
|
|
11
|
-
name = binding.frame_description
|
|
12
|
-
StackFrame.new(file, line, name, binding)
|
|
13
|
-
}
|
|
14
|
-
else
|
|
15
|
-
list = (exception.backtrace || []).map { |frame|
|
|
16
|
-
next unless md = /\A(?<file>.*?):(?<line>\d+)(:in `(?<name>.*)')?/.match(frame)
|
|
17
|
-
StackFrame.new(md[:file], md[:line].to_i, md[:name])
|
|
18
|
-
}.compact
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
if syntax_error?(exception)
|
|
22
|
-
if trace = exception.backtrace and trace.first =~ /\A(.*):(\d+)/
|
|
23
|
-
list.unshift StackFrame.new($1, $2.to_i, "")
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
list
|
|
7
|
+
RaisedException.new(exception).backtrace
|
|
28
8
|
end
|
|
29
9
|
|
|
30
|
-
def self.syntax_error_classes
|
|
31
|
-
# Better Errors may be loaded before some of the gems that provide these
|
|
32
|
-
# classes, so we lazily set up the set of syntax error classes at runtime
|
|
33
|
-
# after everything has hopefully had a chance to load.
|
|
34
|
-
#
|
|
35
|
-
@syntax_error_classes ||= begin
|
|
36
|
-
class_names = %w[
|
|
37
|
-
Haml::SyntaxError
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
Set.new(class_names.map { |klass| eval(klass) rescue nil }.compact)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.syntax_error?(exception)
|
|
45
|
-
exception.is_a?(SyntaxError) || syntax_error_classes.include?(exception.class)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def self.has_binding_stack?(exception)
|
|
49
|
-
exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
|
|
50
|
-
end
|
|
51
|
-
|
|
52
10
|
attr_reader :filename, :line, :name, :frame_binding
|
|
53
|
-
|
|
11
|
+
|
|
54
12
|
def initialize(filename, line, name, frame_binding = nil)
|
|
55
13
|
@filename = filename
|
|
56
14
|
@line = line
|
|
57
15
|
@name = name
|
|
58
16
|
@frame_binding = frame_binding
|
|
59
|
-
|
|
17
|
+
|
|
60
18
|
set_pretty_method_name if frame_binding
|
|
61
19
|
end
|
|
62
|
-
|
|
20
|
+
|
|
63
21
|
def application?
|
|
64
|
-
root = BetterErrors.application_root
|
|
65
|
-
|
|
22
|
+
if root = BetterErrors.application_root
|
|
23
|
+
filename.index(root) == 0 && filename.index("#{root}/vendor") != 0
|
|
24
|
+
end
|
|
66
25
|
end
|
|
67
|
-
|
|
26
|
+
|
|
68
27
|
def application_path
|
|
69
28
|
filename[(BetterErrors.application_root.length+1)..-1]
|
|
70
29
|
end
|
|
@@ -72,7 +31,7 @@ module BetterErrors
|
|
|
72
31
|
def gem?
|
|
73
32
|
Gem.path.any? { |path| filename.index(path) == 0 }
|
|
74
33
|
end
|
|
75
|
-
|
|
34
|
+
|
|
76
35
|
def gem_path
|
|
77
36
|
if path = Gem.path.detect { |path| filename.index(path) == 0 }
|
|
78
37
|
gem_name_and_version, path = filename.sub("#{path}/gems/", "").split("/", 2)
|
|
@@ -88,7 +47,7 @@ module BetterErrors
|
|
|
88
47
|
def method_name
|
|
89
48
|
@method_name || @name
|
|
90
49
|
end
|
|
91
|
-
|
|
50
|
+
|
|
92
51
|
def context
|
|
93
52
|
if gem?
|
|
94
53
|
:gem
|
|
@@ -98,7 +57,7 @@ module BetterErrors
|
|
|
98
57
|
:dunno
|
|
99
58
|
end
|
|
100
59
|
end
|
|
101
|
-
|
|
60
|
+
|
|
102
61
|
def pretty_path
|
|
103
62
|
case context
|
|
104
63
|
when :application; application_path
|
|
@@ -106,23 +65,18 @@ module BetterErrors
|
|
|
106
65
|
else filename
|
|
107
66
|
end
|
|
108
67
|
end
|
|
109
|
-
|
|
68
|
+
|
|
110
69
|
def local_variables
|
|
111
70
|
return {} unless frame_binding
|
|
112
71
|
frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
hash[name] = frame_binding.eval(name.to_s)
|
|
118
|
-
end
|
|
119
|
-
rescue NameError => e
|
|
120
|
-
# local_variables sometimes returns broken variables.
|
|
121
|
-
# https://bugs.ruby-lang.org/issues/7536
|
|
72
|
+
if defined?(frame_binding.local_variable_get)
|
|
73
|
+
hash[name] = frame_binding.local_variable_get(name)
|
|
74
|
+
else
|
|
75
|
+
hash[name] = frame_binding.eval(name.to_s)
|
|
122
76
|
end
|
|
123
77
|
end
|
|
124
78
|
end
|
|
125
|
-
|
|
79
|
+
|
|
126
80
|
def instance_variables
|
|
127
81
|
return {} unless frame_binding
|
|
128
82
|
Hash[visible_instance_variables.map { |x|
|
|
@@ -137,17 +91,15 @@ module BetterErrors
|
|
|
137
91
|
def to_s
|
|
138
92
|
"#{pretty_path}:#{line}:in `#{name}'"
|
|
139
93
|
end
|
|
140
|
-
|
|
94
|
+
|
|
141
95
|
private
|
|
142
96
|
def set_pretty_method_name
|
|
143
|
-
return if RUBY_VERSION < "2.0.0"
|
|
144
|
-
|
|
145
97
|
name =~ /\A(block (\([^)]+\) )?in )?/
|
|
146
98
|
recv = frame_binding.eval("self")
|
|
147
99
|
|
|
148
100
|
return unless method_name = frame_binding.eval("::Kernel.__method__")
|
|
149
101
|
|
|
150
|
-
if
|
|
102
|
+
if Module === recv
|
|
151
103
|
@class_name = "#{$1}#{recv}"
|
|
152
104
|
@method_name = ".#{method_name}"
|
|
153
105
|
else
|