Going in blind
You'll often see Ruby code which looks something like this:
ErrorMessage.new(:message => "I'm afraid I can't let you do that, Dave.", :status => NOT_AUTHORIZED). Some languages, such as Smalltalk and Python, have what are known as "named parameters", which allow a function call to name each parameter passed in. Ruby does not have named parameters but, as in our
ErrorMessage example, we can achieve something similar through hashes.
Let's start with the concept, sans metaprogramming magic. Write a constructor for
ErrorMessage which accepts a named hash for initializing
Ah, what a lovely, readable constructor. Now that we know what it looks like on the outside (which is always an important first step -- understand how an object or method will look through its interface before worrying about how it's implemented), we can use
instance_variable_set to make the insides more concise. We can also abstract this concept out into a module at the same time so we can use this in multiple classes. Give that a shot: blindly assign to instance variables using the keys of the hash with
This example demonstrates one concrete problem with this approach:
@boondoggle was never meant to exist! But because we're using
instance_variable_set, it's created anyway. Let's see how this situation changes when we use
Salvation! We've prevented ourselves from setting the broken / nonexistent instance variable. This solution is certainly better but one problem remains: What if we want to set an instance variable for which there is no setter (as was created by
attr_accessor)? Sometimes we want a constructor which sets state which is purely internal; it can't be changed, nor can it be accessed directly by the outside world. For that sort of constructor we'll need to get a little fancier.