CLI Ruby Gem Project — The Process and Key Takeaways

Ciara Swann
5 min readDec 14, 2020

--

Demo of my CLI project

Project Planning & Structure

In my initial brainstorming of what Ruby CLI gem I wanted to create, I looked to a couple of my interests outside of programming: learning languages and gaming. Initially, I wanted use the API from one of my most visited sites, WaniKani, a SRS (Spaced Repetition System) tool for learning over 2,000 Japanese Kanji and 6,000 vocabulary words. After going through the API, I decided against using the WaniKani API to build my project — it just didn’t seem very accessible to a broader audience and it would require the user to have a baseline understanding of how the Japanese language functions.

I settled on building a CLI tool around League of Legends (LoL), and to make it more accessible, I wanted to build it for newer players who didn’t know much about the game and its characters (champions). There are over 150 playable champions in LoL, all with different characteristics that cater to a wide variety of play styles. My program would allow a user to search through a list of all the champions and select a champion they’re interested in to get more information on that champion (class, difficulty to play, stats, etc.).

I chose two sources from which I would pull the data needed for the program:

  • Riot’s API — Data Dragon
  • The Wikipedia page for League of Legends

After deciding on my data sources, I spent a lot of time watching (and re-watching) the video lecture recordings on the project and reading through the documentation of different CLI Gem projects. Reading through other people’s code was extremely helpful in figuring out how I wanted to structure my own program.

What I wanted to provide with my CLI tool:

  • A brief overview of the game, League of Legends
  • Scraped data from a site (Wikipedia), as well as from an API
  • At least 3 levels of interactivity to get to the Champion-specific information: (first) a main menu that displays the initial options (Overview, Champion List, Exit), (second) when the Champion List option is selected it will bring the user to the enumerated list of Champions where the user can select the champion, (third) then get detailed information of that specific champion.

In an attempt to follow the Single Responsibility Principle (SRP), I created five files for five classes:

  • cli.rb — code for the display on the CLI and functionality
  • champion.rb — code to take the API data and tie it to attributes for each champion
  • overview.rb — code to take the scraped overview data and present it in a more formatted way
  • scraper.rb — scraping data for a general overview of the game
  • api.rb — accessing data on the game’s 152 champions

The Code

api.rb

First, I needed to pull the data on the champions from Riot’s API (Data Dragon). A constant variable was used to store the URL, and the Ruby gem HTTParty was used to parse the JSON into a more accessible hash. During the process of getting to the data I needed, I definitely had to refresh my memory on accessing nested hashes. Pry was extremely helpful in figuring out where the information was that I needed.

champion.rb

In the Champion class the data pulled from the API class is saved, sorted, and displayed. To make my champion list I created two class methods. I needed a method to sort the champions alphabetically by the name attribute while still returning all the other attributes of the class. To keep things DRY (Don’t Repeat Yourself) I reused sorted_champs and then map(&:name) to collect all the name attributes for the champions.

When & (unary ampersand) is combined with a symbol instance, :name, then implicit class cast applies to_proc method to it, like so: all.map(&:name.to_proc) which is in itself a shorthand for all.map{|champion| champion.name} given that all is the class variable holding the array of all champion class instances.

scraper.rb

Since my program is meant for beginners of the game, I wanted to provide a small summary of what League of Legends is and the objective of the game. I decided to scrape the introductory section of the Wikipedia page for LoL, using open-uri and Nokogiri. I only wanted the first two paragraphs at the beginning of the Wikipedia page so I used binding.pry to find the text I needed. By reading the Nokogiri documentation I found that putting [1,2] before .text and after doc.css(“div.mw-parser-output p”) grabbed exactly the two paragraphs I needed.

overview.rb

Initially, I added the overview directly from the Scraper class to the CLI class’ display logic, but it created very long and unformatted lines of text. So, I created this Overview class with a class method to print the scraped data in a more formatted, presentable way. To do that, I wanted to create a text wrapper that would break the strings to a new line if they went over a certain length.

cli.rb

My CLI class contains all of the display logic for the program. I really wanted to make my project interactive (and look good), to do this I used the TTY-Prompt gem. With the TTY-prompt gem I used the select method to create a main menu with options that the user can scroll through using their arrow keys. For the champion list I used TTY-prompt again to create an enumerated list selection of the 152 champions.

Key Takeaways

Takeaway #1: Ruby Gems are amazingly useful tools that will simplify the programming process and add awesome functionality to a project. But, don’t forget to read documentation and figure out the best ways to use them!

Reading the documentation about the gems I used in my project helped immensely in figuring out exactly how they worked and how I could best employ them in my code. Pry for example, was an invaluable tool during the development process, although initially I didn’t see its value when I could just use IRB in the terminal. Only after reading the documentation, watching tutorials, and using it strategically (and often) in my code did I really see how beneficial it was.

Takeaway #2: Don’t be afraid to program just because you don’t want your code to break (again).

Programming my project was a ongoing cycle of coding, breaking, fixing, and doing it all over again. Every time I got my program to run correctly, I found that I was hesitant to get started on my next method, because I was afraid of breaking it again. But, that’s all part of the process and something I learned to lean into it near the end.

Takeaway #3: Try to end programming sessions on a win.

Even if it’s a small one, I always tried to close up shop for the day after having fixed some issue with my program. It’s such an amazing feeling to finally get a certain method that I’ve been scratching my head over running the way I want it to. If I have to wrap-up, then I try to end my programming sessions with this feeling of success. It gets me really excited to program again the next day!

Project GitHub Repository

--

--

Ciara Swann

Software Engineer Intern. Coach @ Rewriting the Code