This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction post for a full table of contents along with some generic principles regarding Design Patterns.

Metaprogramming is an extremely extensive subject that deserves more than a simple review like this, so for those of you more interested, check out this blog post I made about the Ruby Object Model and Metaprogramming. But let’s move on to give just a taste of what metaprogramming is all about.

As you have seen throughout the Ruby implementations of the GoF patterns, some things get a lot easier due to Ruby’s dynamism and metaprogramming is just one of those things that you wouldn’t even dream about doing in static typed languages. A simple usage of metaprogramming that we will explore in this review is the ability to alter the insides of a class at runtime.

In Ruby, instead of writing getters and setters to read/write instance variables, we call a method called attr_accessor and pass it some symbols. Turns out that we can accomplish this same feat with the use of metaprogramming. We’ll call our version ‘accessors':

class Object
	def self.accessors(*names)
		names.each do |name|
			class_eval %Q!
				def #{name}
					@#{name}
				end

				def #{name}=(val)
					@#{name} = val
				end
			!		
		end		
	end
end

class Person
	accessors :name, :age

	def initialize(name, age)
		@name = name
		@age = age
	end
end

pedro = Person.new('Pedro', 19)

puts pedro.name
puts pedro.age

pedro.name = 'Pedro Mateus Tavares'

puts pedro.name

In this code we directly alter the Object class to make our accessor usable by any object, then we open that class and pass it a string to evaluate into Ruby code. This way we ease the burden of people willing to use our code, of course not in this case since there already is attr_accessor, but it’s not hard to find practical uses of this.

A clear example is ActiveRecord, where you gain navigation through related objects simply by declaring a statement such as:

class Post < ActiveRecord::Base
	has_many :comments
end

With a simple line of code we gain easy access to a post’s comments, all thanks to metaprogramming. If you’re still not convinced, I highly suggest a read at the post mentioned in the beggining of this one.

About these ads