Metaprogramming in Ruby
A comprehensive guide to Ruby metaprogramming - learn how to write code that writes code.
First Step on Ruby Metaprogramming
First Week
Let's start learning Ruby Metaprogramming!
Study 0
1st, review the built-in, read-only variable self. Read the following articles:
- self - The current/default object
2nd, review singleton class. Understanding Ruby Singleton Classes is essential for metaprogramming.
3rd, review the scope of variables:
Study 1
Learn about the following metaprogramming methods:
evalinstance_evalclass_eval(aka: module_eval)class_variable_set/class_variable_getclass_variables(Try it out: instance_variables)instance_variable_set(Try it out: instance_variable_get)define_methodconst_set/const_get(Try it out: constants)Class.new(Try it out: Struct.new)binding(Try it out: lambda)send(Try it out: method)remove_method/undef_methodmethod_missing
Study 2
Learn about the singleton class (metaclass):
class << self; self; end Study 3
Learn about the following module methods:
includeextendincludedextended
Also read: Modules and Mixins
Key Concepts
Understand these fundamental metaprogramming concepts:
- Classes are open - You can reopen and modify any class
- Definitions are active - Class and method definitions are executed code
- All method calls have a receiver - Even when implicit (self)
- Classes are objects - They are instances of Class
Second Week
Let's practice how to write a tiny app with Ruby Metaprogramming techniques.
Assignment 1: Define class Dog
Step 1
There are three dogs named Lassie, Fido and Stimpy. Expected output:
"Lassie is dancing"
"Lassie is a smelly doggy!"
"Lassie finds this hilarious!"
"Fido doesn't understand dance"
"Fido is a smelly doggy!"
"Fido doesn't understand laugh"
"Stimpy is dancing"
"Stimpy doesn't understand poo"
"Stimpy doesn't understand laugh" Hints:
- class Dog has three methods: initialize, can, method_missing
- Define static data like:
MSGS = {:dance => 'is dancing', :poo => 'is a smelly doggy!', :laugh => 'finds this hilarious!'}
Step 2
Challenge: Improve to support blocks with the can method:
stimpy.can(:cry){"#{name} cried AHHHH"} Assignment 2: Alias Method Chain
Learn about wrapping methods with logging behavior using alias_method:
class Rubyist
def say!
puts 'hello'
end
def say_with_log!
puts "Calling method..."
puts "hello"
puts "...Method called"
end
alias_method :say_without_log!, :say!
alias_method :say!, :say_with_log!
end
Rubyist.new.say!
#=> Calling method...
# hello
# ...Method called Study Notes
- Study Notes Part 1 - Method lookup, self, send, define_method, method_missing
- Seeing Metaclasses Clearly - Classic article by why the lucky stiff on metaclasses
For More Study
Recommended Book
- Metaprogramming Ruby 2 by Paolo Perrotta
This guide was originally created for the Ruby Metaprogramming course on RubyLearning. It provides a structured approach to learning metaprogramming techniques in Ruby.
This page was originally published on ruby-metaprogramming.rubylearning.com