Metaprogramming Intro
Ruby is a dynamic, beginner-friendly programming language whose open, flexible object model makes metaprogramming — code that writes and inspects code at runtime — both natural and powerful.
Learn Metaprogramming Intro in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll call methods dynamically with send, generate methods with define_method, and intercept unknown calls with method_missing.
What You'll Learn in This Lesson
1️⃣ Dynamic Calls and Introspection
send invokes a method named by a symbol or string, so you can decide which method to call at runtime. Pair it with introspection — respond_to? , instance_methods , ancestors — to ask objects about themselves.
2️⃣ Generating and Intercepting Methods
define_method creates methods at runtime, so you can generate a family of similar methods from a list — no copy-paste. method_missing catches calls to methods that don't exist, letting an object respond to names it was never explicitly given.
Your turn. Generate getter methods from the keys of a settings hash with define_method . Confirm the TODO , then run it.
Route a list of command strings to methods using send — the core of how CLIs dispatch input. Run with ruby dispatch.rb .
📋 Quick Reference — Metaprogramming
Practice quiz
What does metaprogramming mean?
- writing tests
- compiling code
- writing code that writes or inspects code at runtime
- obfuscating code
Answer: writing code that writes or inspects code at runtime. Metaprogramming generates or examines code while the program runs.
What does calc.send(:add, 2, 3) do?
- calls the add method with 2 and 3
- defines add
- raises an error
- returns the symbol :add
Answer: calls the add method with 2 and 3. send invokes a method named by a symbol or string, the same as calc.add(2, 3).
send can accept the method name as:
- only a symbol
- only a string
- only a method object
- a symbol or a string
Answer: a symbol or a string. send takes the name as either a symbol or a string.
Which is safer because it respects method visibility?
- send
- public_send
- __send__
- call
Answer: public_send. public_send will not invoke private methods, unlike send.
What does respond_to?(:add) return when the method exists?
- true
- nil
- false
- the method object
Answer: true. respond_to? returns true when the object has that method.
What does define_method do?
- deletes a method
- calls a method
- creates a method at runtime
- renames a class
Answer: creates a method at runtime. define_method creates methods programmatically, often in a loop.
An advantage of define_method over def is that its body:
- runs faster always
- can close over local variables in scope
- needs no name
- is always private
Answer: can close over local variables in scope. A define_method block closes over surrounding locals; a plain def cannot.
What does method_missing intercept?
- syntax errors
- all method calls
- private methods only
- calls to methods the object does not have
Answer: calls to methods the object does not have. Ruby calls method_missing when you invoke an undefined method.
When overriding method_missing, you should also define:
- initialize
- respond_to_missing?
- to_s
- method_added
Answer: respond_to_missing?. respond_to_missing? keeps respond_to? honest about dynamic methods.
Which familiar feature is itself an example of metaprogramming?
- puts
- require
- attr_accessor
- if/else
Answer: attr_accessor. attr_accessor defines getter/setter methods for you at runtime.