views:

25

answers:

1

I am reading Metaprogramming in Ruby book. In that book, when I was reading about scopegates, the following code was shown

my_var = "Success"

MyClass = Class.new do
  puts "#{my_var} in the class definition"

  define_method :my_method do
    puts "#{my_var} in the method"
  end
end

MyClass.new.my_method

=>Success in the class definition
  Success in the method

Now when I do the execute in the following, I get an error saying undefined method my_method MyClass.new MyClass:0x00000100936a30

MyClass.my_method
NoMethodError: undefined method `my_method' for MyClass:Class
from (irb):11
from /usr/local/bin/irb:12:in `<main>'

Why my_method gets created, when it gets called as MyClass.new.my_method and not MyClass.my_method?

+1  A: 

The define_method method adds an instance method to a class. When you call define_method in your anonymous class, your method is being added as an instance method. To add it as a class method, you have to add it to the metaclass.

The easiest way to do that is with the class << self syntax.

MyClass = Class.new do
  class << self
    define_method(:my_method) do
      puts "class method"
    end
  end
end

MyClass.my_method # => "class method"
Todd Yandell
Thanks for the answer :)
Felix
but now you reach the problem of `class << self` not being a scope gate ;) (would be an excellent exercise for the reader)
thorncp