DEV Community

Joseph Knopke
Joseph Knopke

Posted on

Building a CLI Spell Finder for D&D 5e

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.

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. 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.

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
Enter fullscreen mode Exit fullscreen mode

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:

@damage = spell_data["damage"]["damage_at_slot_level"]
Enter fullscreen mode Exit fullscreen mode

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:

if spell_data["damage"] && spell_data["damage"]["damage_at_slot_level"]
            @damage = spell_data["damage"]["damage_at_slot_level"]
        else
            @damage = "N/A"
        end
Enter fullscreen mode Exit fullscreen mode

I paired this with the code below, in order to actually return a value in my CLI class:

if @spell.damage != "N/A"
      @spell.damage.each do |lvl, dmg|
           puts "Level #{lvl}: #{dmg} damage"
      end
   else
      puts "N/A"
   end
Enter fullscreen mode Exit fullscreen mode

By implementing this code, I made sure my program wouldn't break when presented with a spell that didn't have a damage value.

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!

Discussion (0)