📖 Scenario: Imagine you are building a simple contact list app. You want to add many similar methods to handle different contact details like phone, email, and address without writing repetitive code.
🎯 Goal: You will create a Ruby class that uses metaprogramming to dynamically add methods for different contact details. This will show how metaprogramming helps write less code and keep it flexible.
📋 What You'll Learn
Create a Ruby class called Contact with a hash to store details
Add a list of detail types in a variable called details
Use define_method inside a loop to create getter methods for each detail type
Print the values of the contact details using the dynamically created methods
💡 Why This Matters
🌍 Real World
Metaprogramming is used in Ruby frameworks like Rails to create flexible code that adapts to different data and needs without rewriting methods.
💼 Career
Understanding metaprogramming helps you work with advanced Ruby codebases and build reusable, clean code in professional Ruby development.
Progress0 / 4 steps
1
Create the Contact class with details hash
Create a Ruby class called Contact with an initialize method that sets an instance variable @details to a hash with these exact entries: phone: '123-456-7890', email: 'user@example.com', address: '123 Ruby St'.
Inside the Contact class but outside any method, create a variable called details and set it to an array with these exact symbols: :phone, :email, :address.
Ruby
Hint
Define details = [:phone, :email, :address] inside the class but outside methods.
3
Use define_method to create getter methods
Use a details.each do |detail| loop inside the Contact class (but outside methods) to create getter methods dynamically. Inside the loop, use define_method(detail) that returns @details[detail].
Ruby
Hint
Use details.each do |detail| and inside it define_method(detail) { @details[detail] }.
4
Create an instance and print contact details
Create an instance of Contact called contact. Then print the values of contact.phone, contact.email, and contact.address each on its own line using puts.
Ruby
Hint
Create contact = Contact.new and print each detail with puts contact.phone, etc.
Practice
(1/5)
1. What is the main benefit of metaprogramming in Ruby?
easy
A. It makes Ruby code run faster by compiling to machine code
B. It allows programs to create or modify code while running
C. It prevents errors by checking syntax before running
D. It automatically formats code for better readability
Solution
Step 1: Understand metaprogramming concept
Metaprogramming means writing code that can write or change other code during program execution.
Step 2: Identify the main benefit
This ability makes programs flexible and dynamic, allowing changes without rewriting code.
Final Answer:
It allows programs to create or modify code while running -> Option B
Quick Check:
Metaprogramming = dynamic code creation [OK]
Hint: Metaprogramming means code that writes or changes code [OK]
Common Mistakes:
Confusing metaprogramming with faster execution
Thinking it only formats or checks code
Believing it prevents all runtime errors
2. Which Ruby syntax correctly defines a method dynamically using metaprogramming?
Ruby uses define_method to create methods at runtime.
Step 2: Match correct syntax
define_method(:greet) { puts 'Hello' } uses define_method(:greet) { puts 'Hello' }, which is valid Ruby syntax.
Final Answer:
define_method(:greet) { puts 'Hello' } -> Option D
Quick Check:
define_method = dynamic method creation [OK]
Hint: Use define_method(:name) { ... } to create methods dynamically [OK]
Common Mistakes:
Using incorrect method names like def_method
Wrong block syntax or missing do/end
Confusing method creation with method calls
3. What will be the output of this Ruby code?
class Person
def self.create_attr(name)
define_method(name) { @attributes ||= {}; @attributes[name] }
define_method("#{name}=") { |value| @attributes ||= {}; @attributes[name] = value }
end
create_attr :age
end
p = Person.new
p.age = 30
puts p.age
medium
A. 30
B. nil
C. Error: undefined method
D. 0
Solution
Step 1: Understand dynamic attribute creation
The class method create_attr defines getter and setter methods for the given attribute name using metaprogramming.
Step 2: Trace code execution
After calling create_attr :age, the instance has age and age= methods. Setting p.age = 30 stores 30 in @attributes[:age]. Then puts p.age outputs 30.
Final Answer:
30 -> Option A
Quick Check:
Dynamic getter/setter works = 30 output [OK]
Hint: Dynamic methods store and retrieve values correctly [OK]
Common Mistakes:
Expecting nil because @attributes is not initialized outside methods
Thinking method missing error will occur
Confusing instance variables with local variables
4. Identify the error in this Ruby metaprogramming code:
class Calculator
def self.add_method(name, &block)
define_method(name, &block)
end
add_method(:sum) do |a, b|
a + b
end
end
calc = Calculator.new
puts calc.sum(2, 3)
medium
A. Cannot call define_method inside a class method without instance context
B. Block syntax is incorrect for define_method
C. sum method requires three arguments, but two given
D. No error, code runs and outputs 5
Solution
Step 1: Analyze the metaprogramming usage
The class method add_method tries to call define_method directly, but define_method is a private instance method of Module, not available in the class method context.
Step 2: Identify the error
Calling define_method inside a class method without proper context causes an error.
Final Answer:
Cannot call define_method inside a class method without instance context -> Option A
Quick Check:
define_method must be called on class/module context, not inside class method directly [OK]
Hint: Use class_eval or define_method on self to define methods inside class methods [OK]
Common Mistakes:
Misunderstanding that define_method requires instance context
Thinking block syntax is wrong for define_method
Believing argument count mismatch
5. How can metaprogramming help reduce repeated code when creating multiple similar methods in Ruby?
hard
A. By using global variables to store method names
B. By manually writing each method with similar code
C. By dynamically defining methods based on a list of names
D. By disabling method creation to avoid repetition
Solution
Step 1: Understand the problem of repeated code
Writing many similar methods manually causes repetition and is hard to maintain.
Step 2: Use metaprogramming to define methods dynamically
Metaprogramming lets you loop over a list of method names and create each method automatically, reducing repetition.
Final Answer:
By dynamically defining methods based on a list of names -> Option C
Quick Check:
Dynamic method creation reduces repetition [OK]
Hint: Loop over names and define methods dynamically [OK]
Common Mistakes:
Thinking manual method writing is better
Using global variables incorrectly
Believing disabling methods helps repetition
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.