Search code examples
rubyinstance-eval

instance_eval's behaviour inside a instance method


Below is my snippet which i tried,

class Person
  def test(arg)
    self.class.instance_eval do
      define_method(arg) {puts "this is a class method"}
    end
  end
end

irb(main):005:0> Person.new.test("foo")
=> #<Proc:0x9270b60@/home/kranthi/Desktop/method_check.rb:4 (lambda)>

irb(main):003:0> Person.foo
NoMethodError: undefined method `foo' for Person:Class

irb(main):007:0> Person.new.foo
this is a class method
=> nil

Here am adding a method to the Person class dynamically using instance_eval and define_method. But why is this behaving as instance method?. Is that completely dependent on self? Confused. Can anyone explain me or a reference link also appreciated.


Solution

  • It's because define_method defines instance method of the receiver. Your receiver (self) is Person class, so it defines instance method of Person class. You can achieve what you want accessing to Person's metaclass:

    def test(arg)
      class << self.class
        define_method(arg) { puts 'this is a class method' }
      end
    end
    

    I haven't tested it, but it should work.