When I first started programming, I fell in love with the ability to solve the same problem in many different ways. I also learned the hard way that long-handed tedium ALWAYS beats shorthanded shortcuts when you are first learning a concept.
To that end, I would like to show you a couple different ways to get through writing literally ONLY TWO METHODS in a Ruby exercise called “Unicorn”, part of a series called “Mythical Creatures”, using a magical Ruby tool called an "attr_reader".
I’m using Ruby 2.4.1, the Minitest gem, the Atom text editor, and an incredibly dope font called “Monospace”.
After setting up the basics, I’m ready to make my first test pass.
Let's take a look:
Based on the guiding principles of TDD, let's run the test and see what errors it gives us.
Alright, dig it. Let’s make a method called <name> and reference my instance variable, @name, that I made in the initialize method inside of it!
Let's run my test again and see if it passes.
That’s cool! It works, my test pass and I can move on- and that is ALL that matters at this point.
Upon further inspection, however, we discover though that this method is three lines of code to do…sort of nothing. It's a getter method, sure, which means it shows me the data that it's referencing, but its lot of writing over time if I need to write three lines of code just to read the data the instance variable @name points to. What if I wanted to do this with other attributes of this class? What if it had a name, and a color, and a city of origin, and a breed, and a…I don’t know, other unicorn-y attributes? Is there, then, a way to do the same thing and not take up three lines of code for each attribute? I’m inherently lazy, so I would like to find out.
Here is where the attr_reader comes in. An attr_reader is a shorthanded way to write getter methods as you just did above. It also makes your data public, the same way that writing out a full method does. It looks like this:
With this tool, you can shorthand the <name> method that we wrote earlier, and add others too, which we will see shortly. So, it saves you having to write out all that code over and over again. This becomes especially wonderful when we have lots of instance variables in our initialize methods.
A WORD OF CAUTION
When I was first starting to code, people were telling me “Just use an attr_reader! Just use an attr_reader!!”, so I used them, not understanding fully what it actually does. It took a very wise mentor to help me see that I didn’t know what the hell I was doing, so she made me write everything out by hand FIRST and then let me use the shortcut. I *highly* advise you do the same. Going full in and using a “shortcut” cost me more time in the long run.
We run our test again, and it passes.
Let's look at our next test:
Upon running this test, we see the method <color> doesn’t exist:
Let's write it! First the “long” way, and then using an attr_reader.
And now, using an attr_reader:
Either one fulfills the requirement of writing a method <color> which returns the data associated with the instance variable @color. Both will pass our test, and move on to the next issue, which is another post for another time!
BUT WAIT, ANOTHER WORD OF CAUTION
If you want to add more than one thing to an attr_reader, you MUST put a comma after each one except the last one. My pain, your gain.
Remember, write it out the long way a few times first before you start taking shortcuts-you don’t want to get lost in the woods! Unless the woods are full of unicorns. In which case, get as lost as you want.