Search code examples
rubymetaprogrammingclass-method

Ruby: difference between def and define_method


I'm learning ruby metaprogramming at the moment and while I was playing around and testing stuff, I stumbled upon something I can't seem to find the answer to. Let's say we have the following code:

class Foo
end
Foo.instance_eval do
  define_method("bar") do
    1
  end
end

I would expect this to add a class method called bar to Foo but instead when I call the method it says it's undefined. What baffles me even more is that the same code works when I use def instead of define_method. Both ways seem to work when I try to define an instance method with class_eval as well. So what's really going on here?

Thanks in advance.


Solution

  • Let's make it simple.

    define_method is a method. Or I should say a private class method of Object class. You invoke it by giving it an argument as instance method name you are going to define, and a block which contains the code of the method. apidock has very clear definition. You may want to read documentation.

    def is a keyword. You use this to define methods just as you do all the time. Not really related to meta-programming.

    If you are trying define class method, use class_eval, and give it a string. As its name indicates, instance_eval defines stuffs on instance level. In your code, if you do Foo.instance_methods, you will find the bar method. So if you do Foo.new.bar it returns 1, as TK-421 answered you. But since define_method defines instance_method, as indicated by documentation, regardless if you use class_eval or instance_eval, you will get instance method.

    Here's the documentations you can read and they will answer all you question.

    class_eval: http://apidock.com/ruby/v1_9_3_392/Module/class_eval

    define_method: http://apidock.com/ruby/Module/define_method

    instance_eval: http://apidock.com/ruby/Object/instance_eval

    And don't forget this all mighty: http://www.google.com :D