Ruby Metaprogramming

Metaprogramming means writing code that writes or modifies code at runtime. Ruby makes this remarkably easy — and Rails relies on it heavily.

method_missing

Intercept calls to methods that don't exist:

Ruby
class DynamicGreeter
  def method_missing(method_name, *args)
    if method_name.to_s.start_with?("greet_in_")
      language = method_name.to_s.sub("greet_in_", "")
      greet(language, *args)
    else
      super
    end
  end

  def respond_to_missing?(method_name, include_private = false)
    method_name.to_s.start_with?("greet_in_") || super
  end

  private

  def greet(language, name)
    case language
    when "english" then "Hello, #{name}!"
    when "nepali"  then "Namaste, #{name}!"
    when "hindi"   then "Namaskar, #{name}!"
    else "Hi, #{name}!"
    end
  end
end

greeter = DynamicGreeter.new
puts greeter.greet_in_english("Ram")  # "Hello, Ram!"
puts greeter.greet_in_nepali("Sita")  # "Namaste, Sita!"

define_method

Create methods dynamically:

Ruby
class Person
  %w[name age city].each do |field|
    define_method(field) do
      instance_variable_get("@#{field}")
    end

    define_method("#{field}=") do |value|
      instance_variable_set("@#{field}", value)
    end
  end
end

p = Person.new
p.name = "Sita"
p.age = 21
puts p.name  # "Sita"

send

Call methods by name:

Ruby
class Greeter
  def hello(name) "Hello, #{name}!" end
  def goodbye(name) "Goodbye, #{name}!" end
end

g = Greeter.new
method_name = :hello
puts g.send(method_name, "Ram")  # "Hello, Ram!"

Tips

  • Metaprogramming is powerful but can make code harder to debug.
  • Use it when it simplifies (DRY principle), avoid when it obscures.
  • Prefer define_method over eval — it's safer and faster.

🎉 You have completed the Ruby course!