CLI Project: Harry Potter API
Published: 2020-12-22 04:56:45

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sf6ngkq6hhgqdmr15gfd.png)

Welcome to my first completed project for Flatiron school. This was all done from scratch which was overwhelming at first but ended up being a great learning tool to pull together everything I have been taught so far. I am also so happy with the functionality of my program and hope to expand on it when I have more time and knowledge.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/joh1eec1rlxb1jw9dmpn.png)

The aim of the project was to build a program that provides a CLI, command line interface, for a user to interact with, connected to an external data source. In the image above, you will see that I used an API to gather my data. To be able to access the data in an efficient way, I used JSON to parse it into readable data.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wbpls8wt1v6kbfa81hgs.png)

I chose to make a program that takes a user through the motions of going to Hogwarts and being sorted into their house. The user is then able to meet their house mates by selecting one and hearing some of their attributes. In order to set this up I needed to create a Character class. Its function is to store all of my characters and their attributes in an array until the program would call on them.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/bfs1s77yuchv851wqugj.png)

In the code above I am using the attr_accessor method which stands for attribute accessor. It is actually two methods in one, a reader method and a writer method. To break it down, the reader method returns information stored in an instance variable. Now in order to to make the attribute writable, it needs to be defined in our writer method. However we want our code to be DRY, which stands for don't repeat yourself. If we needed to write out two methods for each of our 4 attributes, it would take up unnecessary space. If we can achieve the same result with less code then that is what we will do. 

Another important part of this class is my initialize method. It allows me to set the initial values for an object. Whenever the new method is called, new objects are created. Initialize must be defined in order to use the new method. Now what will we do with all of these created values? We need somewhere to store them, which is why you see self pushed into @@all. I have made a class variable (@@all) and pushed every instance of self into it. Above the initialize method you can see @@all set to an empty array. This is where I can store my values until needed. Its not enough to store the values, I also need to retrieve them later in my code. My class method, self.all, is how I will call on this array when needed.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/p3m2fllhlq2cmh4qs3qo.png)

This is the rest of my Character class. It consists of three class methods that will be called on inside of my Cli class. The first method allows me to find a character by name instead of only choosing their number out of a list. The next two methods work together to assign a random Hogwarts house that the sorting hat will give you in the beginning of the program. I did find out that I am actually looking through a giant list of characters, since that is how the API has them listed, and then naming the house associated with that character. So instead of choosing a random house directly, I am using .sample to retrieve a random character then saying which house they are in. This same house is used throughout the course of the program until it is exited.

Now that I have all my data loaded and my attributes accessible, it is time to give some functionality to it all. This brings me to my Cli class.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hcv1c6uoe3t6bi5kyf8o.png)

All of my methods defined in the Cli class are instance methods. The first is my start method which is call on in my run file. There I have "Cli.new.start" which essentially starts a new instance of the program once I tell the file to run in the terminal. My start method consists of a couple of strings welcoming you to Hogwarts, and also uses "Api.get_programs" to load all of my API data. My sorting_hat_menu method sets the instance variable @chosen_house to a random Hogwarts house and later interpolates it in the string for the user to read. I used sleep a couple of times to add some dramatic flare for the user, it will make them wait shortly to read the next line. I tired to have all my code listed in order, so each method generally runs down to the next method. This is so the developer does not have to search far for methods if something needs to be changed or looked at. In my main_menu method, I made sure to ask the user for the kind of input I was looking for by including "Type Yes or No" at the end.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/68vu2bg5x2dlrp85r7tm.png)

The character_menu gets the users input and makes a decision based off of that input. I am using a conditional statement (if, elsif, else) to decide the flow of the program. So if the user inputs Yes or yes, they will get a list of characters displayed. If the user inputs No or no, they will exit the program. Any other input from the user will get an invalid choice message and they will be prompted to choose again. In my list_characters method, I am taking each character name from the chosen house and adding a number next to it. I am also telling the program to start at 1 since it will naturally start at 0 if not specified. My character_details_menu_options ask the user to now input a name or number associated with the character they would like to meet.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tcuy5y5icqkrnffpahu1.png)

My character_details_menu method has another conditional statement. The first thing it does is see if the user input was a name from the list. If it is, it will print the character details. If the input is a number between 1 and however long this particular list is, it will chose the associated character and list their details. If it is anything other than a valid name or number, it will output the invalid choice message and bring them back to the previous method. The print_character_details method is filled with many strings. The method takes the character as an argument and then interpolates that character's attributes throughout. I ran into a problem where some characters did not have all of their attributes in the API. Some were empty so I used if and else to give an alternate string if the attribute was empty. All of the characters had a name and a house so I did not need alternate strings for those two.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ajdtbgd70pw0d4agqwxd.png)

This is the end of my Cli class. You can see my meet_more_menu method which allows the program to loop back around if the user would like to, or they may quit. The last three methods are at the bottom of my class because they are small and used to frequently throughout that it would be hard to find another good place to put them. These codes are responsible for accepting user input, letting the user know their choice was invalid, and exiting the program.

This project has been tough and fun at the same time. I remember getting my first method to work and how excited I was, even though the program would abruptly end right after. I am proud of myself for putting in all the work it took to get it to the place it is now. I especially enjoyed being able to work with a Harry Potter API that allowed me to add my own wizard charm to the program. I hope you enjoyed my walk through of the code.