Ruby Metaprogramming Tutorial Part 1 - Introduction and Background

March 23, 2017


Ruby provides a convenient syntax for metaprogramming but it is often unclear when other libraries are using metaprogramming

Ruby is reflective, you can take a look at the properties of all objects.

Ruby’s facilities for DSL authoring don’t change the nature of the language. Ruby’s metaprogramming facilities are inherently tied to Ruby syntax and semantics, and whatever you write has to be shunted into Ruby’s object model.

The often repeated Ruby mantra is “Don’t Repeat Yourself” (DRY). In Ruby this is mainly achieved through the use of Metaprogramming. Metaprogramming is a technique that allows us to write code that returns code that we can use. We will start with a simple example.

class Simple
  def hello
    puts "Hello"
  def method_missing(name, *args, &block)
    puts "tried to handle unknown method %s" % name
    unless args.empty?
      puts "it had arguments: %p" % [args]

We can try loading that class in irb and running a few methods on it.

=> nil
tried to handle unknown method goodbye
=> nil
tried to handle unknown method goodmorning
it had arguments: ["Julio"]
=> nil

The method_missing method catches any method that we attempt to call in an instance of the Simple that is not previously declared. If the method does not exist in Simple then method_missing will be called with all of the details of the non-existent method and print its values to the stdout.

This provides us a way to handle methods we have not defined within in the class. We can use particular details about the method name, arguments or code block to decide what to do next.


Before exploring Metaprogramming further, we need to understand the Ruby object system and introspection. In Ruby, we do everything in the context of an object. Even when we run irb and run code at the top level, we are actually working in main of class Object. At anytime you add methods to a ruby class or override existing methods.

class and instance variables

Class variables are available directly from a class to a class or an instance. Instance variables require making an instance with new and then the instance have access to the variables. Users only have direct access to exposed class and instance variables. However, you can still access private variables through Object methods. Class variables only have one value per class and subclass hierarchy.

class Animal
  @@legs = 2
  def self.legs
    @@legs # class variable getter

puts Animal.legs # => 4

Even when you inherit a class with class variables and change the value in the subclass, the value update will be reflected in the parent class as well. The class variable is shared between the parent and the subclasses.

class Dog << Animal
  @@legs = 4

puts Animal.legs # => 4
puts Dog.legs # => 4

We will remake the dog class with its own class and instance variables. We expose the @name instance variable via attr_accessor.

class Dog
  @@legs = 4
  attr_accessor :name # create getter and setter for Dog  

d = = "Fido"
puts d.instance_variables # => [:@name]

class and instance methods

Class methods are available without making an instance and require the self prefix. They cannot access instance variables. Instance variables are available after creating an instance with new. They can access class and instance variables.

class Foo
    puts 'class method'
  def baz
    puts 'instance method'


The include statement mixes in a module into a class. It is a simple form of multiple inheritance and forms a “is-a” relationship. It makes its methods available to an instance of the class that includes it.

module Foo 
  def foo 
    puts "Hello from Foo"

class Bar
  include Foo
Hello from Foo


The extend statement makes a module’s methods to class. We can call the methods directly from the class without making a new instance.

class Baz
  extend Foo
Hello from Foo


self is a contextual pointer. It points to the current object the program is located in. When we are in the top level of the file, we are located in the main object.

> puts self

> puts self.class

When we declare a method at the top level, it becomes part of the main object. We can see that :m is a method of main.

def m

puts self.method(:m)
=> #<Method: Object#m>

=> [:m ...]

In an object or module self is the current object.

class S
  def put_self
    puts self


module Library
  puts self


BasicObject1 is the parent object of all objects in Ruby. It can be used to create alternative object hierarchies in Ruby. The main hierarchy in Ruby is Object that includes Kernel. It provides a small number of methods.

There are four callback methods that are useful for metaprogramming.


Kernel2 provides a number of useful methods such as Array, Hash, Integer, String, open, puts, etc. Kernel is mixed into Object and main is of class type Object so all of these methods act as global methods in Ruby.

These methods are useful for metaprogramming.


Object3 is the main object in the Ruby object hierarchy. It includes Kernel and is a child of BasicObject. Object has a large number of useful methods for metaprogramming.

define_singleton_method     extend                    instance_of? 
instance_variable_defined?  instance_variable_get     instance_variable_set
instance_variables          is_a?                     kind_of?
method                      methods                   private_methods
protected_methods           public_method             public_methods
public_send                 remove_instance_variable  respond_to?
respond_to_missing?         send