RubyLearning

Helping Ruby Programmers become Awesome!

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:

  • eval
  • instance_eval
  • class_eval (aka: module_eval)
  • class_variable_set / class_variable_get
  • class_variables (Try it out: instance_variables)
  • instance_variable_set (Try it out: instance_variable_get)
  • define_method
  • const_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_method
  • method_missing

Study 2

Learn about the singleton class (metaclass):

class << self; self; end

Study 3

Learn about the following module methods:

  • include
  • extend
  • included
  • extended

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

For More Study

Recommended Book

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