I was given the task of creating a CLI application that pulls data from an external source. Was this task easy? Absolutely not. But did I learn more than I thought possible? The answer is a resounding yes.
Before I start getting technical, I just want to let whomever is reading this know that coding is not easy, but never EVER let the fear of failure keep you from succeeding. I have a tiny voice in my head that likes to tell me I can’t accomplish my goals, but I like to tell that voice to shut up and move to the side.
Git up and GO!
Okay, now lets get technical: my project began by creating a repository on GitHub. Open your terminal and create a directory for your new app. This will create a folder that you can open in your code editor. Go through and create all of your sub-directories utilizing the commands “mkdir” to make directories and “touch” to make files. Afterwards, your setup should look similar to this:
As you can see, I created a file to run my app, a ruby file to require all files necessary to run the app (also known as the environment), and in my library, I have three separate ruby files that are responsible for accessing the API, defining attributes for my Character class, and creating the command line interface. The environment file will require all of the files and gems necessary to run the application. The run file is responsible for….you guessed it, running the app! It also requires the environment file as well. So, when it’s time to run the application, typing “ruby bin/run” will do the job.
HTTParty All Night Long
So I have an API that I want to use, but how do I access it? First, I installed HTTParty to create my Gemfile. I started by making a get request through HTTParty to pull data from the API. I absolutely loved using this gem as it makes the response/request process so much simpler. I didn’t even have to require JSON to parse any data.
Now, I have access to all of the information in one massive array of nested hashes with all of the information I need. Before I continue working on my API request, I immediately create my Character class to start setting attributes for the data I want my user to see. I decided to use mass assignment when setting up attributes in my initialize method, as that is muuchhh easier, as opposed to manually passing though every attribute. Mass assignment allows us to initialize objects with a hash. As you can see below, we use string interpolation to enable the key to correspond with the attributes we are setting and the value will represent the values of the attributes. We use the .send method as simply another way to call a method that allows us to be more dynamic as we write our code.
Now for the fun stuff! My CLI class is where I will be creating and defining everything that I want the user to see and do. I began by asking myself:
- What is the overall purpose of this application?
- What is the role of the user? In other words, what is their responsibility when interacting with the app?
- When and how will the user be prompted to make a selection? If their input is incorrect, how will I inform them?
All of these questions (plus many more) assisted me in creating a methodology for how I wanted this app to flow.
This is the first thing the user will see, so it was important for me to incorporate the color green (a prominent theme throughout the show). This greeting calls on the API to retrieve all character information, displays a list of character names to the user, and then calls the sub_heading method. Self is used frequently throughout my code and I’ll explain why. As you’ll see later, self is simply a keyword that gives you access to the current object. For the purposes of this particular project, I used self frequently to define my class methods. That way, when you’re as indecisive as me and keep changing the name of the class, you don’t have to change it in the definitions as well. Quick note: ever confused about the value of self (it can take some time to get the hang of it)? Just head into pry, type self, and ka-zam! You can see the value. It’s extremely helpful for beginners like myself to quickly find the value if you are unsure.
Creating the API
Moving forward, the next step was for me to finish creating an API class that is responsible for accessing data from an external source. I chose Breaking Bad because not only did I find the most beautiful API, but this is one of the best shows ever written (sorry, I don’t make the rules).
Here we can see the beautiful self yet again. And now after my .get call to the API, I want to iterate over the array to give me the exact attributes that I want to pull from the data. Don’t forget to call the Character class at the very end and pass in the new hash as an argument (because that’s what I did. I completely forgot)!! Remember, the .new method will not only create a new instance of the class, but because it is accepts an argument, it will then pass that argument to the initialize method. Also note that because it was the last line of the method, it is implicitly returned, so writing “return” is redundant and not necessary in this case. All of my classes will work together to make this CLI!
Dreaming of My CLI
The remainder of my project lies within my CLI class. After I define my greeting, what’s next? I used the .each iteration again to display a list of characters to the user, because even the biggest fans may forget the character names. Error messaging was also extremely key. This CLI requires the user to spell both first and last names correctly AND input a correct corresponding number to view more information. If either of those requirements are not met, the user will receive an error message and a prompt to start over or exit the application. My instructor emphasized the importance of DRY (Don’t Repeat Yourself). Originally, I had multiple strings located in multiple methods where I would ask the user if they were choosing to leave, but instead, why not define an exit method? Defining the exit method was a much easier and cleaner way to ensure the user has the ability to exit the application. I also incorporated the same logic when I was asking the user a “yes or no” question. Instead of repeatedly typing puts statements, I created a yes_or_no method that I could easily call in other methods to achieve the same end result.
The title of this post is “Failing Upwards” because that is precisely what I did. I ran into a lot of errors, a lot of confusion, and at one point I questioned if I even knew what I was doing. But the reality is, every error I encountered taught me something new about my code. Misplaced arguments and incorrect calls to the wrong method helped me learn exactly what methods are required to accomplish this CLI. Additionally, I have some refactoring to do. I would like to clean up all of the “if — else” statements I have in one of my methods, and I know through the use of ternary operators I can achieve a much cleaner code. I wanted my users to have a fun experience looking at their favorite characters and finding out information they may not have known from watching the show. It took a while, but that’s what I accomplished!