better_errors 0.9.0 → 1.0.0.rc1
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 +14 -6
- data/.travis.yml +1 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +2 -2
- data/README.md +7 -16
- data/better_errors.gemspec +0 -8
- data/lib/better_errors.rb +45 -31
- data/lib/better_errors/code_formatter.rb +2 -2
- data/lib/better_errors/code_formatter/html.rb +11 -4
- data/lib/better_errors/code_formatter/text.rb +2 -2
- data/lib/better_errors/error_page.rb +2 -1
- data/lib/better_errors/middleware.rb +10 -5
- data/lib/better_errors/repl.rb +2 -2
- data/lib/better_errors/repl/basic.rb +1 -1
- data/lib/better_errors/repl/pry.rb +11 -6
- data/lib/better_errors/stack_frame.rb +41 -7
- data/lib/better_errors/templates/main.erb +37 -5
- data/lib/better_errors/templates/variable_info.erb +4 -3
- data/lib/better_errors/version.rb +1 -1
- data/spec/better_errors/code_formatter_spec.rb +11 -11
- data/spec/better_errors/error_page_spec.rb +20 -13
- data/spec/better_errors/middleware_spec.rb +35 -16
- data/spec/better_errors/repl/basic_spec.rb +1 -1
- data/spec/better_errors/repl/pry_spec.rb +9 -6
- data/spec/better_errors/repl/shared_examples.rb +16 -20
- data/spec/better_errors/stack_frame_spec.rb +71 -30
- data/spec/better_errors_spec.rb +63 -3
- data/spec/spec_helper.rb +1 -0
- metadata +10 -110
- data/CONTRIBUTING.md +0 -9
- data/TIPS_AND_TRICKS.md +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NjYyNmFjYTQ1MjJmN2M4ZTIyODQ0MGY2YzNjOTE5ODU5ODU2NzQyZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OWRjYzA4NTI5YzI1YWViZDAyMjlhN2RmOWQ4NDA3MWYwMTlkMzUyNA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MTBhZDMwMTI5MzFiZTYwNzNlNzk2YWI2NTE2OTYzODc2ODZjZjFkYjQ4MGIw
|
10
|
+
MGI5ZGM5NzVkMzQzZmUzYzBjOTJlYmYzMWZjMDZlMjZjYmQzNjQ2NDM5OTY5
|
11
|
+
NTdlNDMwMjFhNTlhY2VhYWU1YzVlMTA2ZGZmYmI0OGYwYzYxNmQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTZmNjc4ZTRmZjlhZTZhOTJhMjc1MDM0NDAwMDMyYjdkNzY4MDdkOTNlN2Nk
|
14
|
+
YjBhMjhlNjE3YTZhZmFkODU1OTk1MGFkMjk4MWRhMzljNzc4ZTczMzdhMTBk
|
15
|
+
MTRjNWJhMGU4NDllYWFiMDFiOWNiMmNhZTQ4OGU2MzE3MGQyMzQ=
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2013 Charlie Somerville
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Better Errors
|
1
|
+
# 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
|
|
@@ -67,7 +67,7 @@ require "better_errors"
|
|
67
67
|
|
68
68
|
configure :development do
|
69
69
|
use BetterErrors::Middleware
|
70
|
-
BetterErrors.application_root =
|
70
|
+
BetterErrors.application_root = __dir__
|
71
71
|
end
|
72
72
|
|
73
73
|
get "/" do
|
@@ -75,27 +75,18 @@ get "/" do
|
|
75
75
|
end
|
76
76
|
```
|
77
77
|
|
78
|
-
## Compatibility
|
79
|
-
|
80
|
-
* **Supported**
|
81
|
-
* MRI 1.9.2, 1.9.3, 2.0.0
|
82
|
-
* JRuby (1.9 mode) - *advanced features unsupported*
|
83
|
-
* Rubinius (1.9 mode) - *advanced features unsupported*
|
84
|
-
|
85
|
-
[](https://travis-ci.org/charliesome/better_errors)
|
86
|
-
|
87
78
|
### Unicorn, Puma, and other multi-worker servers
|
88
79
|
|
89
80
|
Better Errors works by leaving a lot of context in server process memory. If
|
90
|
-
you're using a web server that runs
|
81
|
+
you're using a web server that runs multiple "workers" it's likely that a second
|
91
82
|
request (as happens when you click on a stack frame) will hit a different
|
92
83
|
worker. That worker won't have the necessary context in memory, and you'll see
|
93
84
|
a `Session Expired` message.
|
94
85
|
|
95
|
-
If this is the case for you, consider
|
96
|
-
in `development`. Another option would be to use
|
97
|
-
single-process
|
98
|
-
development.
|
86
|
+
If this is the case for you, consider turning the number of workers to one (1)
|
87
|
+
in `development`. Another option would be to use Webrick, Mongrel, Thin,
|
88
|
+
or another single-process server as your `rails server`, when you are trying
|
89
|
+
to troubleshoot an issue in development.
|
99
90
|
|
100
91
|
## Get in touch!
|
101
92
|
|
data/better_errors.gemspec
CHANGED
@@ -18,14 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
20
|
s.required_ruby_version = ">= 1.9.2"
|
21
|
-
|
22
|
-
s.add_development_dependency "rake"
|
23
|
-
s.add_development_dependency "rspec", "~> 2.12.0"
|
24
|
-
s.add_development_dependency "binding_of_caller"
|
25
|
-
s.add_development_dependency "pry"
|
26
|
-
s.add_development_dependency "simplecov"
|
27
|
-
s.add_development_dependency "yard"
|
28
|
-
s.add_development_dependency "redcarpet"
|
29
21
|
|
30
22
|
s.add_dependency "erubis", ">= 2.6.6"
|
31
23
|
s.add_dependency "coderay", ">= 1.0.0"
|
data/lib/better_errors.rb
CHANGED
@@ -11,25 +11,32 @@ require "better_errors/code_formatter"
|
|
11
11
|
require "better_errors/repl"
|
12
12
|
|
13
13
|
module BetterErrors
|
14
|
+
POSSIBLE_EDITOR_PRESETS = [
|
15
|
+
{ symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" },
|
16
|
+
{ symbols: [:macvim, :mvim], sniff: /vim/i, url: proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" } },
|
17
|
+
{ symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" },
|
18
|
+
{ symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" },
|
19
|
+
]
|
20
|
+
|
14
21
|
class << self
|
15
22
|
# The path to the root of the application. Better Errors uses this property
|
16
23
|
# to determine if a file in a backtrace should be considered an application
|
17
24
|
# frame. If you are using Better Errors with Rails, you do not need to set
|
18
25
|
# this attribute manually.
|
19
|
-
#
|
26
|
+
#
|
20
27
|
# @return [String]
|
21
28
|
attr_accessor :application_root
|
22
|
-
|
29
|
+
|
23
30
|
# The logger to use when logging exception details and backtraces. If you
|
24
31
|
# are using Better Errors with Rails, you do not need to set this attribute
|
25
32
|
# manually. If this attribute is `nil`, nothing will be logged.
|
26
|
-
#
|
33
|
+
#
|
27
34
|
# @return [Logger, nil]
|
28
35
|
attr_accessor :logger
|
29
36
|
|
30
37
|
# @private
|
31
38
|
attr_accessor :binding_of_caller_available
|
32
|
-
|
39
|
+
|
33
40
|
# @private
|
34
41
|
alias_method :binding_of_caller_available?, :binding_of_caller_available
|
35
42
|
|
@@ -41,64 +48,61 @@ module BetterErrors
|
|
41
48
|
|
42
49
|
# Returns a proc, which when called with a filename and line number argument,
|
43
50
|
# returns a URL to open the filename and line in the selected editor.
|
44
|
-
#
|
51
|
+
#
|
45
52
|
# Generates TextMate URLs by default.
|
46
|
-
#
|
53
|
+
#
|
47
54
|
# BetterErrors.editor["/some/file", 123]
|
48
55
|
# # => txmt://open?url=file:///some/file&line=123
|
49
|
-
#
|
56
|
+
#
|
50
57
|
# @return [Proc]
|
51
58
|
def self.editor
|
52
59
|
@editor
|
53
60
|
end
|
54
|
-
|
61
|
+
|
55
62
|
# Configures how Better Errors generates open-in-editor URLs.
|
56
|
-
#
|
63
|
+
#
|
57
64
|
# @overload BetterErrors.editor=(sym)
|
58
65
|
# Uses one of the preset editor configurations. Valid symbols are:
|
59
66
|
#
|
60
67
|
# * `:textmate`, `:txmt`, `:tm`
|
61
68
|
# * `:sublime`, `:subl`, `:st`
|
62
69
|
# * `:macvim`
|
63
|
-
#
|
70
|
+
#
|
64
71
|
# @param [Symbol] sym
|
65
|
-
#
|
72
|
+
#
|
66
73
|
# @overload BetterErrors.editor=(str)
|
67
74
|
# Uses `str` as the format string for generating open-in-editor URLs.
|
68
|
-
#
|
75
|
+
#
|
69
76
|
# Use `%{file}` and `%{line}` as placeholders for the actual values.
|
70
|
-
#
|
77
|
+
#
|
71
78
|
# @example
|
72
79
|
# BetterErrors.editor = "my-editor://open?url=%{file}&line=%{line}"
|
73
|
-
#
|
80
|
+
#
|
74
81
|
# @param [String] str
|
75
|
-
#
|
82
|
+
#
|
76
83
|
# @overload BetterErrors.editor=(proc)
|
77
84
|
# Uses `proc` to generate open-in-editor URLs. The proc will be called
|
78
85
|
# with `file` and `line` parameters when a URL needs to be generated.
|
79
|
-
#
|
86
|
+
#
|
80
87
|
# Your proc should take care to escape `file` appropriately with
|
81
88
|
# `URI.encode_www_form_component` (please note that `URI.escape` is **not**
|
82
89
|
# a suitable substitute.)
|
83
|
-
#
|
90
|
+
#
|
84
91
|
# @example
|
85
92
|
# BetterErrors.editor = proc { |file, line|
|
86
93
|
# "my-editor://open?url=#{URI.encode_www_form_component file}&line=#{line}"
|
87
94
|
# }
|
88
|
-
#
|
95
|
+
#
|
89
96
|
# @param [Proc] proc
|
90
|
-
#
|
97
|
+
#
|
91
98
|
def self.editor=(editor)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
when :emacs
|
100
|
-
self.editor = "emacs://open?url=file://%{file}&line=%{line}"
|
101
|
-
when String
|
99
|
+
POSSIBLE_EDITOR_PRESETS.each do |config|
|
100
|
+
if config[:symbols].include?(editor)
|
101
|
+
return self.editor = config[:url]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
if editor.is_a? String
|
102
106
|
self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } }
|
103
107
|
else
|
104
108
|
if editor.respond_to? :call
|
@@ -116,8 +120,18 @@ module BetterErrors
|
|
116
120
|
def self.use_pry!
|
117
121
|
REPL::PROVIDERS.unshift const: :Pry, impl: "better_errors/repl/pry"
|
118
122
|
end
|
119
|
-
|
120
|
-
|
123
|
+
|
124
|
+
# Automatically sniffs a default editor preset based on the EDITOR
|
125
|
+
# environment variable.
|
126
|
+
#
|
127
|
+
# @return [Symbol]
|
128
|
+
def self.default_editor
|
129
|
+
POSSIBLE_EDITOR_PRESETS.detect(-> { {} }) { |config|
|
130
|
+
ENV["EDITOR"] =~ config[:sniff]
|
131
|
+
}[:url] || :textmate
|
132
|
+
end
|
133
|
+
|
134
|
+
BetterErrors.editor = default_editor
|
121
135
|
end
|
122
136
|
|
123
137
|
begin
|
@@ -36,9 +36,9 @@ module BetterErrors
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def each_line_of(lines, &blk)
|
39
|
-
line_range.zip(lines).map
|
39
|
+
line_range.zip(lines).map { |current_line, str|
|
40
40
|
yield (current_line == line), current_line, str
|
41
|
-
|
41
|
+
}
|
42
42
|
end
|
43
43
|
|
44
44
|
def highlighted_lines
|
@@ -6,14 +6,21 @@ module BetterErrors
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def formatted_lines
|
9
|
-
each_line_of
|
9
|
+
each_line_of(highlighted_lines) { |highlight, current_line, str|
|
10
10
|
class_name = highlight ? "highlight" : ""
|
11
|
-
sprintf '<pre class="%s">%
|
12
|
-
|
11
|
+
sprintf '<pre class="%s">%s</pre>', class_name, str
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def formatted_nums
|
16
|
+
each_line_of(highlighted_lines) { |highlight, current_line, str|
|
17
|
+
class_name = highlight ? "highlight" : ""
|
18
|
+
sprintf '<span class="%s">%5d</span>', class_name, current_line
|
19
|
+
}
|
13
20
|
end
|
14
21
|
|
15
22
|
def formatted_code
|
16
|
-
%{<div class="code">#{super}</div>}
|
23
|
+
%{<div class="code_linenums">#{formatted_nums.join}</div><div class="code">#{super}</div>}
|
17
24
|
end
|
18
25
|
end
|
19
26
|
end
|
@@ -6,9 +6,9 @@ module BetterErrors
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def formatted_lines
|
9
|
-
each_line_of
|
9
|
+
each_line_of(context_lines) { |highlight, current_line, str|
|
10
10
|
sprintf '%s %3d %s', (highlight ? '>' : ' '), current_line, str
|
11
|
-
|
11
|
+
}
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -40,11 +40,12 @@ module BetterErrors
|
|
40
40
|
return { error: "REPL unavailable in this stack frame" }
|
41
41
|
end
|
42
42
|
|
43
|
-
result, prompt =
|
43
|
+
result, prompt, prefilled_input =
|
44
44
|
(@repls[index] ||= REPL.provider.new(binding)).send_input(code)
|
45
45
|
|
46
46
|
{ result: result,
|
47
47
|
prompt: prompt,
|
48
|
+
prefilled_input: prefilled_input,
|
48
49
|
highlighted_input: CodeRay.scan(code, :ruby).div(wrap: nil) }
|
49
50
|
end
|
50
51
|
|
@@ -64,8 +64,8 @@ module BetterErrors
|
|
64
64
|
def allow_ip?(env)
|
65
65
|
# REMOTE_ADDR is not in the rack spec, so some application servers do
|
66
66
|
# not provide it.
|
67
|
-
return true unless env["REMOTE_ADDR"]
|
68
|
-
ip = IPAddr.new env["REMOTE_ADDR"]
|
67
|
+
return true unless env["REMOTE_ADDR"] and !env["REMOTE_ADDR"].strip.empty?
|
68
|
+
ip = IPAddr.new env["REMOTE_ADDR"].split("%").first
|
69
69
|
ALLOWED_IPS.any? { |subnet| subnet.include? ip }
|
70
70
|
end
|
71
71
|
|
@@ -85,10 +85,10 @@ module BetterErrors
|
|
85
85
|
rescue Exception => ex
|
86
86
|
@error_page = @handler.new ex, env
|
87
87
|
log_exception
|
88
|
-
show_error_page(env)
|
88
|
+
show_error_page(env, ex)
|
89
89
|
end
|
90
90
|
|
91
|
-
def show_error_page(env)
|
91
|
+
def show_error_page(env, exception=nil)
|
92
92
|
type, content = if @error_page
|
93
93
|
if text?(env)
|
94
94
|
[ 'plain', @error_page.render('text') ]
|
@@ -99,7 +99,12 @@ module BetterErrors
|
|
99
99
|
[ 'html', no_errors_page ]
|
100
100
|
end
|
101
101
|
|
102
|
-
|
102
|
+
status_code = 500
|
103
|
+
if defined? ActionDispatch::ExceptionWrapper
|
104
|
+
status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
|
105
|
+
end
|
106
|
+
|
107
|
+
[status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }, [content]]
|
103
108
|
end
|
104
109
|
|
105
110
|
def text?(env)
|
data/lib/better_errors/repl.rb
CHANGED
@@ -40,19 +40,24 @@ module BetterErrors
|
|
40
40
|
@output = Output.new
|
41
41
|
@pry = ::Pry.new input: @input, output: @output
|
42
42
|
@pry.hooks.clear_all
|
43
|
-
@continued_expression = false
|
44
|
-
@pry.hooks.add_hook :after_read, "better_errors hacky hook" do
|
45
|
-
@continued_expression = false
|
46
|
-
end
|
47
43
|
@fiber.resume
|
48
44
|
end
|
49
45
|
|
50
46
|
def send_input(str)
|
51
47
|
local ::Pry.config, color: false, pager: false do
|
52
|
-
@continued_expression = true
|
53
48
|
@fiber.resume "#{str}\n"
|
54
|
-
[@output.read_buffer,
|
49
|
+
[@output.read_buffer, *prompt]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def prompt
|
54
|
+
if indent = @pry.instance_variable_get(:@indent) and !indent.indent_level.empty?
|
55
|
+
["..", indent.indent_level]
|
56
|
+
else
|
57
|
+
[">>", ""]
|
55
58
|
end
|
59
|
+
rescue
|
60
|
+
[">>", ""]
|
56
61
|
end
|
57
62
|
|
58
63
|
private
|
@@ -1,8 +1,10 @@
|
|
1
|
+
require "set"
|
2
|
+
|
1
3
|
module BetterErrors
|
2
4
|
# @private
|
3
5
|
class StackFrame
|
4
6
|
def self.from_exception(exception)
|
5
|
-
if exception
|
7
|
+
if has_binding_stack?(exception)
|
6
8
|
list = exception.__better_errors_bindings_stack.map { |binding|
|
7
9
|
file = binding.eval "__FILE__"
|
8
10
|
line = binding.eval "__LINE__"
|
@@ -16,12 +18,36 @@ module BetterErrors
|
|
16
18
|
}.compact
|
17
19
|
end
|
18
20
|
|
19
|
-
if
|
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
|
21
25
|
end
|
22
26
|
|
23
27
|
list
|
24
28
|
end
|
29
|
+
|
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
|
25
51
|
|
26
52
|
attr_reader :filename, :line, :name, :frame_binding
|
27
53
|
|
@@ -85,7 +111,11 @@ module BetterErrors
|
|
85
111
|
return {} unless frame_binding
|
86
112
|
frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
|
87
113
|
begin
|
88
|
-
|
114
|
+
if defined?(frame_binding.local_variable_get)
|
115
|
+
hash[name] = frame_binding.local_variable_get(name)
|
116
|
+
else
|
117
|
+
hash[name] = frame_binding.eval(name.to_s)
|
118
|
+
end
|
89
119
|
rescue NameError => e
|
90
120
|
# local_variables sometimes returns broken variables.
|
91
121
|
# https://bugs.ruby-lang.org/issues/7536
|
@@ -110,14 +140,18 @@ module BetterErrors
|
|
110
140
|
|
111
141
|
private
|
112
142
|
def set_pretty_method_name
|
143
|
+
return if RUBY_VERSION < "2.0.0"
|
144
|
+
|
113
145
|
name =~ /\A(block (\([^)]+\) )?in )?/
|
114
146
|
recv = frame_binding.eval("self")
|
115
|
-
|
116
|
-
|
147
|
+
|
148
|
+
return unless method_name = frame_binding.eval("::Kernel.__method__")
|
149
|
+
|
150
|
+
if Kernel.instance_method(:is_a?).bind(recv).call Module
|
117
151
|
@class_name = "#{$1}#{recv}"
|
118
152
|
@method_name = ".#{method_name}"
|
119
153
|
else
|
120
|
-
@class_name = "#{$1}#{recv.
|
154
|
+
@class_name = "#{$1}#{Kernel.instance_method(:class).bind(recv).call}"
|
121
155
|
@method_name = "##{method_name}"
|
122
156
|
end
|
123
157
|
end
|