2

Why can't I see @obj.instance_variables in Object when method_missing is invoked?

module Arena
  class Place
    def initialize obj
      @obj = obj
      method_missing_in_obj
      @obj.instance_variable_set(:@unit, '10')
      puts @obj.instance_variables
      yield @obj
    end
    def method_missing_in_obj
      def @obj.method_missing method, *args, &blk
        puts @obj.instance_variables
        super
      end
      self
    end
  end
end

Arena::Place.new(Object.new) do |obj|
  puts obj.instance_variable_get(:@unit)
  puts obj.foo
end

$> ruby test_me.rb:

=> @unit
=> 10
=> in `method_missing': undefined method `foo' for #<Object:0x007fd89b1c96e0 @unit="10"> (NoMethodError)

1 Answer 1

2

This is a subtle bug! The problem is that you're calling @obj.instance_variables when you define @obj.method_missing. Remember, that defines a method in @obj's singleton class, so when you use @obj inside the method definition, you're asking for @obj's instance variable @obj which is nil (and nil has no instance variables).

All you need to do is remove the explicit receiver, since @obj is implicitly the receiver for methods defined in its singleton class.

def method_missing_in_obj
  def @obj.method_missing method, *args, &blk
    puts instance_variables
    super
  end
  self
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.