[ruby-core:68928] [Ruby trunk - Feature #10982] Clarify location of NoMethod error

From: mail@...
Date: 2015-04-18 19:41:30 UTC
List: ruby-core #68928
Issue #10982 has been updated by Yuki Nishijima.


It wasn't so hard to implement this in pure Ruby, the last example doesn't =
work, though.

```ruby
# -*- coding: utf-8 -*-
class NoMethodError
  REPL_LABELS =3D {
    "irb_binding" =3D> -> { Readline::HISTORY.to_a.last },
    "__pry__"     =3D> -> { ::Pry.history.to_a.last }
  }

  def to_s
    msg =3D super
    msg << "\n\n".freeze
    msg << "  #{code}\n"
    msg << "  #{marker}\n"
  rescue
    super
  end

  def code
    # Memoize since the #backtrace_locations method creates a lot of object=
s.
    @code ||=3D begin
      loc =3D backtrace_locations.first

      if REPL_LABELS.include?(loc.label)
        REPL_LABELS[loc.label].call
      elsif File.exist?(loc.absolute_path)
        File.open(loc.absolute_path) do |file|
          file.detect { file.lineno =3D=3D loc.lineno }
        end
      end
    end.to_s.strip
  end

  def marker
    code.strip.gsub(/(.*)(#{name}).*/) do
      (" ".freeze * $1.size.pred) + '^'.freeze + ("=E2=80=BE".freeze * $2.s=
ize)
    end if !code.empty?
  end
end

# works
e =3D 1.foo rescue $!
puts e
# =3D> undefined method `foo' for 1:Fixnum
#
#  e =3D 1.foo rescue $!
#       ^=E2=80=BE=E2=80=BE=E2=80=BE

# works.
e =3D 1.send(:bar) rescue $!
puts e
# =3D> undefined method `bar' for 1:Fixnum
#
#  e =3D 1.send(:bar) rescue $!
#             ^=E2=80=BE=E2=80=BE=E2=80=BE

# works
@foo =3D ->{ true }
e =3D (@foo.call && @bar.call) rescue $!
puts e
# =3D> undefined method `call' for nil:NilClass
#
#  e =3D (@foo.call && @bar.call) rescue $!
#                        ^=E2=80=BE=E2=80=BE=E2=80=BE=E2=80=BE

# doesn't work
e =3D (@something.call && @else.call) rescue $!
puts e
# =3D> undefined method `call' for nil:NilClass
#
#  e =3D (@something.call && @else.call) rescue $!
#                               ^=E2=80=BE=E2=80=BE=E2=80=BE=E2=80=BE
```

----------------------------------------
Feature #10982: Clarify location of NoMethod error
https://bugs.ruby-lang.org/issues/10982#change-52194

* Author: Richard Schneeman
* Status: Open
* Priority: Normal
* Assignee:=20
----------------------------------------
In Ruby, the error `NoMethodError` on happens frequently, especially when i=
t occurs on `nil`. This error can be confusing to beginners since, many of =
them think there is a problem with the method instead of the receiver. This=
 error can be confusing to advanced developers when there are multiple meth=
od calls in the on the same line. In this example it is unclear if `foo` or=
 `bar` returned `nil`:

```
foo.call && bar.call
NoMethodError: undefined method `call' for nil:NilClass
```

I would like to make this a better error message and to indicate where the =
exception occurs.

```
@foo.call && @bar.call
                 ^----
NoMethodError: The method `call` is undefined on receiver nil:NilClass
```

Now it is more clear that the `@bar` is currently `nil` and that is the sou=
rce of the error. I believe exposing this information will help developers =
of all abilities.=20




--=20
https://bugs.ruby-lang.org/

In This Thread

Prev Next