Metaprogramming in Ruby
Ruby's metaprogramming capabilities allow you to write code that writes code, making it highly flexible and dynamic.
Dynamic Method Definition
        Use define_method to define methods at runtime.
      
class MyClass
  define_method :dynamic_method do |arg|
    puts "Dynamic method called with #{arg}"
  end
end
obj = MyClass.new
obj.dynamic_method("Hello")
      
      Open Classes
Ruby allows you to reopen and modify existing classes, even built-in ones.
class String
  def shout
    self.upcase + "!"
  end
end
puts "hello".shout  # Output: HELLO!
      
      Dynamic Method Calls
        Use send to call methods dynamically.
      
class MyClass
  def my_method(arg)
    puts "Called with #{arg}"
  end
end
obj = MyClass.new
obj.send(:my_method, "Hello")  # Output: Called with Hello
      
      Class Macros
        Class macros are methods that generate code at the class level. A common example is attr_accessor.
      
class MyClass
  def self.create_method(name)
    define_method(name) do
      puts "Method #{name} called"
    end
  end
end
MyClass.create_method(:new_method)
obj = MyClass.new
obj.new_method  # Output: Method new_method called
      
      Method Missing
        Use method_missing to handle calls to undefined methods.
      
class MyClass
  def method_missing(name, *args)
    puts "Method #{name} called with #{args}"
  end
end
obj = MyClass.new
obj.undefined_method("Hello")  # Output: Method undefined_method called with ["Hello"]
      
      Reflection
Ruby provides reflection methods to inspect and manipulate objects at runtime.
class MyClass
  def my_method
    puts "Hello"
  end
end
obj = MyClass.new
puts obj.class  # Output: MyClass
puts obj.methods(false)  # Output: [:my_method]
      
      Best Practices
- Avoid Overuse: Metaprogramming can make code harder to read and debug. Use it sparingly.
 - Documentation: Document metaprogramming code thoroughly to help others understand its purpose.
 - Testing: Write tests for metaprogramming code to ensure it behaves as expected.
 - Performance: Be mindful of performance implications, especially in large applications.