60 days into my Flatiron bootcamp and the first project—a CLI application—is due in a few hours.
Looking back over everything I learned, all the parts needed to build a CLI app were covered, but the idea of building something from scratch was still intimidating.
Yes, we had built CLI apps as part of the course material, but this was different. The safety net of a test suite or being able to hit the ask a question button was missing, this time.
That, in addition to the unknown of how much time it would take to build had me feeling anxious.
if anxiety == unknown
puts "screams into the void"
Luckily, anxiety caused by the unknown can be resolved by planning and presenting yourself with facts instead of “what ifs”. So, planning felt like a logical first step to tackling this project. This post will cover the planning steps I took to get started, related resources and thoughts on what I would like to implement in the future.
I was very tempted to jump right in. To get ahead of the clock. But just like grocery shopping without a list leads to disastrous results, making a list of what skills, tech and methods I need would help me to stay focused and avoid being surprised.
In my case, there were specific project requirements so I started there. Reading over the requirements, making notes and asking a question if needed was the first step. I did this before writing any code.
Even if you do not have project requirements, think about what you want your CLI app to do. Here are some questions that came to mind for me:
- What is the purpose of the program? What will it do?
- What outside resources or data will it need?
- How will the user interact with the CLI?
- Will it take any inputs from the user?
- What outputs should it have?
For my application, I wanted to display data showing burger restaurants (or restaurants that sold burgers) nearby.
Programmatically, this is what I want to happen.
- Get all local burger restaurants
- Display name, rating, and location
- Prompt user to input a restaurant
- Display more information
It doesn’t have to be perfect, just enough to the core concepts across. This also helped me to avoid scope creep with my own project.
Relating to technology, I knew I needed a website to scrape data from (as part of the project requirements) and settled The 15 Best Places for Burgers in Baltimore on Foursquare. I choose this page because the source code had well-named CSS classes that would make it easy to target and scrape the sections I needed.
I wanted to use Bundler to set up the project and Nokogiri to do the actual scraping, so took the time to read through their documentation. For me, reading documentation (and project requirements) in detail helped to ease my anxiety, feel prepared and maximize my time.
At this point, I was ready to start coding.
Building the CLI
Getting the skeleton of my project was the very first step. At first, I wasn’t sure which files or folders were best practices. Then, the Bundler documentation made it very easy to get started.
In the terminal, all you have to do is the following:
bundler gem name_of_your_project
For my project, it looked like this:
bundler gem burger_finder
Small note that I learned the hard way. Ruby uses snake case as a naming convention. While
bundler gem burger-finder isn’t wrong…it does make for weird folder formatting, so it’s best to stick with snake case.
At this point, I will admit, I felt stuck. While I knew how to build the methods I would need to create the parts of my CLI, I did not know how to get the CLI its self to work. Or, what all these mystery files that Bundler created are for. So, as opposed to muddling my way through it, I read Dissecting my Ruby Project Skeleton which I found helpful in understanding the parts I was working with.
Once I could get my program running via ruby bin/start in the command line, I was good to start building my methods and chaining them together as needed.
For the most part, building the pieces went smoothly. However, getting the pieces to work together while returning the correct data did take some work. Setting up a console so that I can peak into the code (like with binding.pry) instead of running the whole program was helpful too.
My biggest blocker was getting 403 errors when scraping my webpage. Understandably, I had been flagged for hitting the site too often in a short amount of time.
As a workaround, I created a static version of the main page for the initial scrape (since I would be hitting that one the most) but will go out to the venue’ specific page for the details. A quick search showed the following as a fix that so far, as kept a 403 error from happening when scraping the detail pages.
Nokogiri::HTML(open(url, 'User-Agent' => 'ruby'))
Earlier, I mentioned scope creep as something I wanted to avoid. I find it easy to want to do all-of-the-things when its best to focus on the basic requirements first, then refactor and add features afterward.
That said, I here as some of what I would like to add to this project in the future:
- Implementing an API: It turns out Foursquare’s Places API is perfect for this! Getting set up was easy and free but I did not have enough time to implement it before my project due date. Understanding the API and how to manipulate and display the data is on my to-do list.
- Location by input: I’d also like to get location data from the user via input so that I can display more relevant restaurant information. Again, the Places API would be perfect for this, but there may have been a way to append a zip code to a URL which would be used to scrape data. For example,
www.fourquare.com?search=burger?zip=90201 would display burger joints in Beverly Hills.
- Edge cases. Right now, my application assumes the user will only enter correct inputs. In a real-world application, this is not realistic. I’d like to include messaging that responds to an input that is outside of the available range. For example, if the user wants to know about the 20th restaurant object when there are only 15.
- Error Handling. Custom error messaging was covered briefly in our course material, but I would like to explore it more. If something was broken how can I communicate that with a user? Error handling ties into the edge cases I mentioned above.
Overall, I am happy with how my burger_finder project came out. It’s not perfect, true, but I implemented a lot of what I learned in the past two months. It’s weird to think that earlier this year, I had never written a line of Ruby.
Now, I’m not far off from being able to create a program from scratch and publish it as a gem. I’ve gotten better at troubleshooting errors, debugging and making progress even when it feels like I am stuck or out of time.
Now that my project has been submitted, it’s time to sit back, reflect and prepare for the project review.
Maybe I’ll grab a burger for dinner. Is there an app for that?