Building a CLI Spell Finder for D&D 5e
Tags: ruby, cli, beginners
Published: 2021-01-10 22:15:11

It took me longer than I'd like to admit to come up with an idea for this CLI project to end Phase 1. I spent several days trying to wrap my head around using APIs and scraping, but I still found myself ridiculously confused on even just the basics of navigating an API.

<img width="75%" style="width:75%" src=https://media.giphy.com/media/2fTOT5PhBUdJbDeVLH/giphy.gif>

After watching and rewatching a dozen different videos and lectures on APIs, I thought I was finally ready to start working on my own project. The public API that immediately caught my eye was a database for [D&D 5e](https://www.dnd5eapi.co/docs/#base). While i'm not the most knowledgable or experience D&D player, it is a game that I thoroughly enjoy playing. On top of that, this API is incredibly readable and user-friendly, as it allows access to a vast amount of information through a variety of endpoints. 

When beginning my project, I decided to narrow my focus on spells, as it was a large enough pool of data to play around with, but not so large where I could get lost on my first ruby CLI project.

<img width="66%" style="width:66%" src=https://media.giphy.com/media/l0ExsgrTuACbtPaqQ/giphy.gif>

My first idea was allowing the user to search for a spell by name, then returning a bunch of relevant data about the spell they searched for. I knew I would need a class that created different Spell objects, as well as a class to get those objects from the API.

Implementing this functionality was simple enough: I just need to get user input, use the __downcase__ and __gsub__ methods to add the correct formatting, and then plug the result into the url.

(I know I said it was "simple enough," but you won't believe how excited I was when I finally was able to return a hash I could use and pull data from)

The resulting hash contained a bunch of information about the inputted spell, but I noticed something strange about the formatting pretty quickly. __Some of the keys had array values, while some had string values__. I know this is exceedingly common, but when I first tried pulling info from my hash it definitely tripped me up. 

With enough prying around, I was able to return the values I wanted, but just when I thought I was good to go- __AN ERROR__!!!

```
undefined method `[]' for nil:NilClass
```
After scratching my head for a while, I realized that one of the attributes I was pulling from the spell's hash must've had an empty value. See, I was searching through the hash and defining instance variables like so:
```ruby
@damage = spell_data["damage"]["damage_at_slot_level"]
```
But what if my spell doesn't have any damage?? An empty value would still be assigned to @damage, and trying to call the damage getter method results in our error.

So, I needed to change my code so that spells without damage would simply return Damage:N/A, rather than breaking my code.

I come up with the block below:
```ruby
if spell_data["damage"] && spell_data["damage"]["damage_at_slot_level"]
            @damage = spell_data["damage"]["damage_at_slot_level"]
        else
            @damage = "N/A"
        end
```
I paired this with the code below, in order to actually return a value in my CLI class:
```ruby
if @spell.damage != "N/A"
      @spell.damage.each do |lvl, dmg|
           puts "Level #{lvl}: #{dmg} damage"
      end
   else
      puts "N/A"
   end
```
By implementing this code, I made sure my program wouldn't break when presented with a spell that didn't have a damage value. 

<img width="66%" style="width:66%" src=https://media.giphy.com/media/XreQmk7ETCak0/giphy.gif>

While it may be a simple solution upon reflection, overcoming this error felt like a big success at the time! I added some more functionality to the program: allowing users to search for a list of spells by level or by school of magic. Also, after the search results were presented, I allowed for users to either search again or exit the application.

I know this is a super basic project, but it was definitely exciting to see the potential of a CLI. Building out the app on my own was definitely a rewarding process (albeit frustrating at times). 

I'm already thinking about the ways I could expand the current application!