What are #method_missing and #send? Why are they useful?

method_missing, as the name suggests, is called when the method cannot be found. With this powerful meta-programming tool, we can create dynamic methods, such as the dynamic finder in Active Record

class Legislator
  # Pretend this is a real implementation
  def find(conditions = {})
  end
  
  # Define on self, since it's  a class method
  def self.method_missing(method_sym, *arguments, &block)
    # the first argument is a Symbol, so you need to_s it if you want to pattern match
    if method_sym.to_s =~ /^find_by_(.*)$/
      find($1.to_sym => arguments.first)
    else
      super
    end
  end
end

Send is also a powerful tool for dynamic method invocation. Its function is to pass a method to the object in the form of parameters

class Box
  def open_1
    puts "open box"
  end

  def open_2
    puts "open lock and open box"
  end

  def open_3
    puts "It's a open box"
  end

  def open_4
    puts "I can't open box"
  end

  def open_5
    puts "Oh shit box!"
  end 
end

box = Box.new

box.send("open_#{num}")