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, Programming not meant for common mortals? Programming in the next dimension?. But the truth is, 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.
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.
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.
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.
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.