Trial & Error : One month in and Building a CLI Application
Since learning Ruby language, I felt a sense of accomplishment every time I completed a lab because coding is completely new to me. I’m enjoying learning Ruby because for the most part it is very legible and clear, which makes it easier for a first time coder to understand whether or not a line of is working. This course has been an intense journey thus far because our cohort has been applying various skills rapidly and learning in ways we are not completely familiar with; for example, text-based learning from labs and such. Despite the pace and difficulties, I feel more comfortable googling for help and staring at a blank file waiting to be written compared to my first day of Flatiron School.
As I worked my way down the list of modules we had to complete, the idea of the final CLI (command line interface) project kept popping up in my mind. I knew the Flatiron school would not test us on things we have not learned nor expect an advanced project, but I still feel nervous even though I am confident with what my application can do because I know it comes down to pass or fail in order to move onto the next phase of the course. The expectation of us working alone and building an application from start to finish was very daunting, but as I worked through it step by step, it wasn’t as gruesome as I’d initially thought. I realized I tend to expect the worst, which has its pros and cons. I stressed myself more than I should in trying to complete the project as a whole, so instead I finished one task at a time.
I started brainstorming about what to base my project on after my cohort lead sent me a a link to free APIs (application programming interfaces) and after I watched some Youtube videos she sent me as well. An API basically exposes data from a company and allows the public to use that information; by doing so, people are able to add that info to new or existing applications for greater functionality. I chose to take information from an API rather than scraping data because I heard horror stories of how websites could change overnight and that would significantly break all the code that worked before that change. APIs on the other hand, are for the most part, consistent and don’t change very often. Once I watched how to start the actual build of the project on VS Code I was feeling better with figuring out where to begin, at that point I just had to figure out what I wanted my application to do!
I skimmed through the list of free APIs and went straight to the food and drink section. I was originally thinking about listing out vegetarian recipes and their details, but I figured I should probably do something that isn’t as commonly found. When I saw the free Open Brewery Database I made up my mind. I’ve always been a “foodie” and “drinkie,” so why not help myself out with future indecisiveness by creating an application that can give me a list of breweries in California to choose from to chug my next beer flight!
Programmatically, I wanted my application to do exactly this:
- Welcome the user
- Prompt user to input his/her name or exit
- Prompt user to input a number to either see all CA breweries or exit
- Display the most breweries possible alphabetically
- Prompt user to input a brewery name to see its details or exit
- Display name, brewery type, location, phone number, and website
- Prompt user to input a number either to see all CA breweries again or exit
I jumped right in by creating some base folders and files by typing this into my terminal:
bundle gem beer_o_clock_cli
I was a little overwhelmed with starting because I had to ensure the CLI, API, and Brewery files ran first before I even started coding. I wasn’t exactly comfortable tying these files together (even though our lessons went over the process before) because most of the labs already required the files inside of them so all we had to do was type out the correct code to pass the tests. Once I was able to enter ruby bin/run to start the program, I was feeling much better. As I continued to progress in building my application, I wanted to make sure I was completing the necessary requirements before figuring out how to refactor my code and add unique features. At this point I just wanted to make sure my code did not break while trying to run it.
Building the Brewery class was definitely the most familiar to me. I knew what attributes I wanted to assign each brewery object by looking at the API url. I made sure to only pick attributes that only pertained to the brewery location, an option that gives the user a phone number to call in case he or she would like to get in touch with the brewery, and the brewery’s website, just in case the user would like to know even more-so about that specific brewery. I created an @@all class variable to keep track of all brewery instances in an array and a #save instance method to save each instance of a new brewery object in that @@all array. I initialized each brewery object with it’s properties using mass assignment in order to simplify my code and not have to type out all the attributes. Instead of this:
def initialize(name, brewery_type, street, city, state, postal_code, country, phone, website_url)@name = name@brewery_type = brewery_type@street = street@city = city@state = state@postal_code = postal_code@country = country@phone = phone@website_url = website_urlsaveend
I could simply have this:
def initialize(attributes_hash)attributes_hash.each {|key, value| self.send("#{key}=", value) if self.respond_to?("#{key}=")}saveend
By doing this, the initialize method is taking in an attributes_hash and iterating over each key/value pair in the attributes hash. The method is setting values to a key, if that key exists, but only for the attributes that have setters and getters. Since the attributes hash has more attributes than I want to use in my application, I’m customizing my application to only .respond_to? and create key/value pairs to attributes that I have created to have setters and getters already when I made them attr_accessors. The .send method is creating those instance variables as shown above.
Building the API class took a shorter amount of time than I thought, but then I realized it is because the API class’ sole concern is to take the data retrieved from the API endpoint and instantiate ruby brewery objects with each brewery from the breweries_array. The API class consumes data from the external source and lets me create methods to act on the the ruby objects created from that source in my CLI and Brewery classes.
The CLI class was the hardest class for me to work on. I had plenty of errors throughout it and I learned quickly that I needed to make sure I tested out each line of code I added to see what went wrong. I started off with various syntax errors, which I got familiar with and problem solved right away after getting the hang of it. I ran into two errors consistently: the first one was that my program would kick out my user without my user specifically telling the program he or she wanted to exit first, and the second error was that I when the user did enter “exit” and certain prompts, he or she would have to enter “exit” multiple times in order to leave the program when they should only have to enter “exit” once to leave. When it came to the first error, I was not calling on my menu method again at the end of whichever method I was in and by no doing so, the program did not cycle back so the user was not able to get prompted again. For the second error, I was putting my #menu method too many times within other methods to the point where the user was too many level deep, which is why they had to exit out of every level they were nested within.
Trying to problem solve those two major errors alongside some others that I needed help with from my cohort lead showed me that I did not fully understand the way control flow works within code. I was calling methods inside of methods and not knowing how to get back to the top level without certain lines of code being repeated. Without my my cohort lead showing us how to use binding.pry and even during our 1:1, I would not have been able to solve the issues at hand because I got lost and didn’t know where I was exactly while running through the code at times.
I wanted to make sure that both of these errors were fixed throughout the program because in a fully functioning real like application, these issues do not exist and let the user exit whenever he or she decides to do so.
One of the biggest lessons I learned while doing my first project was that it is okay to ask for help. For the most part, I really try to do everything in my power to fully understand the material myself and definitely utilize all the resources I have at my fingertips in order to solve a problem at hand; however, there were times where I would find myself looking at my screen of code (longer than I probably should have alone) missing that one syntax error or just not connecting that dots because I was already looking at it for how many hours straight working on it. It is okay to get a budge in the right direction from a fresh brain and mentor who wants you to succeed and do well. Candice, my cohort lead for the Part Time Software Engineering course, definitely did that for me and helped explain to me what was happening in certain parts of my code that I was not fully comprehending.
I am proud of what I have created in my beer_o_clock_cli application. I really would love to add more functionality to it, either now or in the future, and I already have ideas of what I could add to make it even more user friendly. I believe the only issue right now for changing it and making it more complicated is me figuring out how to implement those changes and make them run correctly and how I would like them to. I noticed while coding along and getting in the zone of building my project, I really never feel like the project is finished. There’s always something about the code that you could change or add to it. Sometimes I would get so caught up in the work that my wife would ask me if I would like to take a break and eat something just because it is addictive in a way to make you want to finish writing a method or see it run efficiently from start to finish without breaking. This project has been a fun and stressful experience, but I’m happy that it lets us really create something of our own and become so involved in it like how we would in a real life situation at a future job.