Flowdock
define_method(...) public

Defines an instance method in the receiver. The method parameter can be a Proc or Method object. If a block is specified, it is used as the method body. This block is evaluated using instance_eval, a point that is tricky to demonstrate because define_method is private. (This is why we resort to the send hack in this example.)

   class A
     def fred
       puts "In Fred"
     end
     def create_method(name, &block)
       self.class.send(:define_method, name, &block)
     end
     define_method(:wilma) { puts "Charge it!" }
   end
   class B < A
     define_method(:barney, instance_method(:fred))
   end
   a = B.new
   a.barney
   a.wilma
   a.create_method(:betty) { p self }
   a.betty

produces:

   In Fred
   Charge it!
   #<B:0x401b39e8>
Show source
Register or log in to add new notes.
November 5, 2009
4 thanks

define_method with parameters

Just to be clear, you can do this:

define_method(:my_method) do |foo, bar| # or even |*args|
  # do something
end

This means same as:

def my_method(foo, bar)
  # do something
end

If you want to define method with parameters that have default values, you need to get a bit more creative and do something like this:

define_method(:my_method) do |foo, bar|
  bar ||= {}
  # do something
end
May 5, 2010
0 thanks

Avoiding the "multiple values for a block parameter" warning

As pointed out below, you can also have optional parameters. But you will get something like “warning: multiple values for a block parameter (0 for 1)” if you omit them.

You can avoid those warnings by passing *args and picking the parameters yourself:

define_method :that_method do |*args|

  foo = args[0] || 'my default'
  # ...
end

Now the warning will be gone. Just make sure you fetch your parameters from *args and assign a default value (unless you want them to default to nil).