I'm trying to figure out how to dynamically create methods
class MyClass
def initialize(dynamic_methods)
@arr = Array.new(dynamic_methods)
@arr.each { |m|
self.class.class_eval do
def m(*value)
puts value
end
end
}
end
end
tmp = MyClass.new ['method1', 'method2', 'method3']
Unfortunately this only creates the method m but I need to create methods based on the value of m, ideas?
class_eval is a method of the Module class, meaning that the receiver will be a module or a class. The block you pass to class_eval is evaluated in the context of that class. Defining a method with the standard def keyword within a class defines an instance method, and that's exactly what happens here.
instance_eval is a similar method on the Object class that takes in Ruby code embedded in a string and two other optional arguments. One of the major differences between eval and instance_eval is that with instance_eval you have the choice of explicitly handling the context of self .
Metaprogramming is a technique by which you can write code that writes code by itself dynamically at runtime. This means you can define methods and classes during runtime.
There are two accepted ways:
Use define_method:
@arr.each do |method|
self.class.class_eval do
define_method method do |*arguments|
puts arguments
end
end
end
Use class_eval with a string argument:
@arr.each do |method|
self.class.class_eval <<-EVAL
def #{method}(*arguments)
puts arguments
end
EVAL
end
The first option converts a closure to a method, the second option evaluates a string (heredoc) and uses regular method binding. The second option has a very slight performance advantage when invoking the methods. The first option is (arguably) a little more readable.
define_method(m) do |*values|
puts value
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With