RUBY

Ruby on Steroids: The Magic of MetaProgramming – An Unexpected Journey


We have all been hearing about metaprogramming. Metaprogramming is one of those words that seems to exist purely to scare people. Are we talking about programming beyond programming? Xtreme Programming in the Dojo? Programming made for ruby ninjas use, and that it simply isn’t for common mortals? Programming in the next dimension?. But the truth is that metaprogramming isn’t something scary at all. In fact, metaprogramming—at least as it is practiced in the Ruby world—is a very workman set of coding techniques that allow you to get the results you need with less code.

What is MetaProgramming

Metaprogramming is a technique by which you can write code that writes code by itself dynamically at runtime. This means you can define methods and classes during runtime. Crazy, right? In a nutshell, using metaprogramming you can reopen and modify classes, catch methods that don’t exist and create them on the fly, create code that is DRY by avoiding repetitions, and more.

Magic Spells

Throughout this journey, we are going to be learning a lot of ruby spells that makes it possible to practice magic(metaprogramming). Let’s begin this journey by learning some of the fundamental spells.

1. eval

Evaluates the Ruby expression(s) in string. Ruby’s eval takes in a string as the argument, which means that it is possible for one to accept user input or read code off of a file and get it evaluated from within your program – essentially re-programming the way your program behaves.

2. instance_eval

Evaluates a string containing Ruby source code, or the given block, within the context of the receiver (object). What this means is that if you create a method using instance_eval in the body of a class, that method will be a class method. However, if you create a method with instance_eval in the body of an instance method, that method will become a singleton method of the object created from the class as soon as the method that has the instance_eval has been invoked. instance_eval cannot be used to create normal instance methods in class. It can only be used to create class methods and singleton methods. In the version of instance_eval that takes a String, the optional second and third parameters supply a filename and starting line number that are used when reporting compilation errors.

3. class_eval (aka: module_eval)

The module_eval and class_eval methods operate on modules and classes rather than on objects. The class_eval is defined as an alias of module_eval. They are used to add normal instance methods to a class. class_eval method is not available in an instance of a class.

4. class_variable_get & class_variable_set

class_variable_get method is used to retrieve the value of a class variable while class_variable_set updates the value of a class variable with a new value. Both method are only available to class objects.

5. instance_variable_get & instance_variable_set

instance_variable_get method is used to retrieve the value of an instance variable while instance_variable_set updates the value of an instance variable with a new value.

 

Conclusion

We have seen some of the few spells you can cast using metaprogramming in this blog post. Why exactly should you care about metaprogramming? Well it is because metaprograming allows you to create more flexible code, be it through beautiful APIs or easily testable code. More than that though, it allows you to do that using powerful and elegant programming techniques and syntax. Metaprogramming allows you to create code that is DRY, highly reusable, and extremely concise.

In part 2 of this journey, we will explore more spells you can cast using metaprogramming in ruby. Subsequent blog posts tagged with Ruby on Steriods will also be talking about metaprogramming in one form or the other. So expect blog posts on DSL(external & internal), Hooks, Use cases for metaprogramming etc.

Ikem Okonkwo

About Ikem Okonkwo

Ruby Evangelist, .NET Advocate. Trainer at @andela. Passionate about education and lifelong learning. Loves good food and soccer.