We’re going to play with method_missing and less so, monkey patching. All of this code is designed to work in one source file or irb session. It will run procedurally from beginning to end. So you can copy it in pieces into a single .rb file or follow along in irb. No need to break it out into separate files or restart irb.
We’ll start with a simple person class that is initialized with a name and an age.
Creating a person is as simple as passing “James” and 99 as arguments.
Now I have a Person object as expected. The twist comes in when you look at this line by itself and realize that you can’t get what 99 is. Is it the age? Is it the problems? Of course, you might opt to simply get rid of the constructor and set the instance variables manually. But let’s try to do something more fancy.
First, we’ll try to invoke a method that doesn’t exist.
We will get an exception here. For the sake of our single source file, we’ll catch the exception and continue.
So when we try to call #create_with_name_and_problems so that 99 is clearly a problem and not an age argument, the method doesn’t exist. We could create that method but that’s not very scalable, we’d have to create every permutation of possible construction options.
Instead what we are going to do is use method_missing to handle calls to unknown methods and at the same time set the instance variables and return an object.
First we reopen the Person class (monkey patch) and redefine a parameter-less initialize method. Next we create a method_missing method on the class object that looks for any method that starts with “create_with_”. If it does then it creates a new object with the correct instance variables set. Finally, the respond_to? method ensures that our Person class is advertising that #create_with_ methods are valid to outside calls.
Ok, so now our Person object is ready to be used. We can create James again this time with a name and a number of problems. We can even create a person with all three attributes and vary the order.
So in actuality, this is a bit contrived. It’s cool to have these dynamic methods created for us but doing this way is a little too much work just to get parameterized constructors. The better way would be to use a hash for initialization. See below: