Over the past two weeks I've finally built my first portfolio project for Flatiron School. 🎉
Something I should have expected from this process, but didn't, was the sheer quantity of little mistakes, strange little errors, and little (ok, maybe moderate) struggles I'd have to overcome, work through, problem solve, and get over.
The project outline is to build a CLI app that scrapes a website for information, and then utilizes that scraped information to provide the user with at least one-layer deep of information to interact with.
For my project, I decided to scrape the website for Adagio Teas. I worked for them roughly 3 years ago, and have been addicted to their teas ever since. And because I'd worked there, and worked closely with the website, the CTO, and the teas, it seemed like a great option for a scraping project. It also allowed me to build my project to go three-layers-deep for information: one layer to grab all the categories, one layer to grab all the tea names, and another layer to grab each teas detailed info (description, ingredients, and pricing).
My first (of a thousand) little mistakes was thinking that anything about scraping can be straight forward. From needing to
.strip text of white space and line breaks, to figuring out when and how to figure out if an item was out of stock (surprise, it's actually a button!) gave me a lot to work through. Just the process of building the scraper out to retrieve the information I was looking for, and plugging that in to object instances with correct formatting (tea names and descriptions are strings, the price list is a hash, and the ingredients are an array or string or nothing, depending on the tea), took me the better part of a week.
One of my biggest little mistakes was a lack of understanding when it comes to control flow. When you call a method inside a method inside a method, which method is really in control? And how do you get yourself back to that top layer?
In the structure of the app, the method that runs the main app loop is called
.call, and it's within
.call that all of the other methods that run that app are, well, called. There are some
if statements to control what the user does and when. I wanted to give the user a perpetual option to go 'back' throughout the application. And one of my biggest mistakes was calling
.call from within a method that
.call calls... and I think you might be able to see how/whyI got a little confused there.
I ended up having all kinds of looping issues and exiting issues and struggled to wrap my head around what was happening. And it wasn't until I had an extremely insightful impromptu 1:1 with my cohort lead/technical coach that I was able to full understand what was happening, and which method was in control and when. I learned that throwing in as many
binding.pry as I could stand and just watching the flow of my application/methods helped so much more than I expected. It taught me a really valuable lesson not only about general problem solving and debugging, but about programmatic thinking, control flow, looping, and how easy it is to get caught up in that flow and not really know where you are.
Oh, and in case you were wondering, instead of calling
.call , I just needed to
return the method so I could exit into to the
.call loop and keep on loopin'.
And lastly, I learned something through basic trial and error, and the help of a friend: if you create a Ruby Gem with an executable file, the name of your executable file is what you call when you want to run the Gem. So maybe don't call your
bin file something as generic as
run... Now that I know that, it seems so obvious but it took a Zoom call with one of my classmates to figure out why the heck I couldn't get my Gem to work. (That, and some file path issues, but we won't talk about that one just yet, because I still don't entirely understand what happened there.)
One of the biggest things I learned/was reminded of is to never be afraid to ask for help, to reach out to a fellow dev or student, and just ask questions or bounce ideas off of someone. There were times during this project where I'd hop on a call with my cohort lead and solve my own problem just by talking it out with her, or her asking me leading questions that helped me come a solution on my own. I turned to group chats full of dev friends, a Slack channel full of fellow students, and even to the CTO of Adagio Teas (when their security settings decided I had scraped their site enough and blocked my IP!). Asking for help or opinions or insights is not a weakness. It's a skill. And it's one I'm glad I'm improving on.
All in all, I am extremely proud of what I accomplished, extremely critical of what I built, and itching to refactor, restyle, and extend the functionality of this project. But not until after I've had a good long break over the weekend.
Oh, and if you'd like to install the Gem and see what it can do, just open your terminal and run
gem install TeaLI, then run
TeaLI and have some tea-related CLI fun!
You can also take a look at the GitHub repo, if you're so inclined:
This is a CLI app built in Ruby as a portfolio project for the Flatiron School Software Engineering curriculum.
The app utilizes the Adagio Teas website (www.adagio.com). On start up the app will scrape the Adagio website for some basic tea info.
Once finished scraping the user will be prompted to make one of three choices: browse all available tea by category, search by ingredient, or receive a surprise tea.
Heads Up: The "search by ingredient" option requires additional loading time during which all teas will be scraped for ingredient information, in order to allow the user to search for their desired ingredient. Some great options to search for: cinnamon, hibiscus, apple, chocolate, and vanilla.
Installing the TeaLI:
To install TeaLI, open your terminal and enter the following command:
gem install TeaLI
Running the TeaLI:
To run the TeaLI application simply type
TeaLI into your terminal