Project

General

Profile

Actions

Bug #17426

closed

method_missing can't override kernel#system method anymore

Added by freiden (charles fd) over 3 years ago. Updated over 3 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
[ruby-core:101629]

Description

Hello,

It seems like I found a behavior change on the way method missing is working on Ruby 2.7.2 in comparison with 2.6.6.
method_missing can't intercept call to a method called system.

The following code help reproducing the behavior

class Klass

  def method_missing(meth, *args, &blk)
    if %i[system foo].include?(meth)
      puts 'behavior not reproductible'
    else
      super
    end
  end

  # Work on 2.6.6
  def call_system_from_self
    self.system
  end

  # Doesn't work on both
  def call_system_from_implicit_self
    system
  end

  # Work on both
  def call_foo_from_self
    self.foo
  end

  # Work on both
  def call_foo_from_implicit_self
    foo
  end

  # Doesn't work on both
  def call_system_with_send_from_self
    self.send(:system)
  end

  # Work on both
  def call_foo_with_send_from_self
    self.send(:foo)
  end

  # Work on both
  def call_system_with_public_send
    self.public_send(:system)
  end

  # Work on both
  def call_foo_with_public_send
    self.public_send(:foo)
  end

end

Is it an expected behavior change in 2.7.2?

Actions #1

Updated by jeremyevans0 (Jeremy Evans) over 3 years ago

  • Status changed from Open to Rejected

This is expected. From NEWS-2.7.0:

* Calling a private method with a literal +self+ as the receiver
  is now allowed. [Feature #11297] [Feature #16123]

Because you are allowed to call private methods when using self in 2.7.0, method_missing will not be called. If you need to use system specifically, alias it to another method name and then undef it, and have method_missing call the aliased method.

Updated by znz (Kazuhiro NISHIYAMA) over 3 years ago

If you want to intercept system on both, you can use undef or undef_method.

class Klass
  undef_method :system
end

Updated by nobu (Nobuyoshi Nakada) over 3 years ago

Or, use other than the literal self.

self.system("true") #=> runs `true` command

(self).system("true") #=> private method `system' called for main:Object (NoMethodError)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0