Creating a Dog Bio CLI with Ruby

When creating a project and having a wide range of selection had me thinking. What would be something that would be cool and might be used by other people? I thought about my previous job being a dog walker and then it hit me, why not help spread a little more info on certain types of dogs as a project? Dogs just like most animals have many different species with a plethora amount of information about each one, on top of it, who doesn't love dogs?

Planning the CLI(Command line Interface) was tough. What did I want my MVP(Minimum Viable Product) to do? Well for starters I wanted it to greet whomever decides to use it of course, but besides that, how would I deliver on the biography of each dog? I decided to scrape information of a website called Purina. Purina is a website that specializes in pet foods but also had a large data base of dog breeds. So I scraped a couple of URL’s using something called Nokogiri(Website parser that allows me to grab information from the website). So now that I had a website to grab the data from, there came the big part. Putting everything together and creating a menu for any user to have ability to input certain key words to receive information from my CLI. Now here is the hardest part! Explaining all the code in English!

So I called my gem something extremely original… I called it “dog”. Not the best name but something to keep track of easily within my files. Now Let’s dissect my menu code Step By Step. First I created a class called “class Dog::CLI”.

call method

Next I created a method called “call” which will start immediately for the user and will call upon another two methods, list_dogs and menu.

list_dogs method

The list_dogs method calls upon a string which is displayed for the user saying “List of Dogs”. Line 11 calls upon another ruby file called dog_bio.rb along with the class method named “self.list” and tags it to an instance variable I decided to name “dogs” to keep it simple. Now with that done, I called upon the instance variable then have it run through each dog’s breed name and having it displayed in a string form for the user to see with the index(i) so it would be displayed as:

The index is the number displayed so each dog has a number attached to it in a list form

Now with the biggest method in my project… the menu method!

menu method

The first part of the method is all about the users input. I had “input” set to nil and then used the “while” condition and had it set to input != “exit”. In ruby terms the “!=” means “doesn’t equal”, which means if the user does not input “exit” then it skips the very long string and continues to the rest of the code.

Flow Chart of the “while” condition

Now after the while loop. There is code that has input set to gets.chomp.downcase. What does that mean???

“gets” is what the user puts in and ruby interacts with whatever the user decides to put in with chomp taking out certain things at the end of the users input string such as “exit\n”.chomp -> “exit”. Finally downcase puts any input from the user into a lowercase string so the CLI will have an easier time to interpret what the user is asking for; instead of putting in “PUg” and having the CLI not understanding, it will be accepted with downcase as “pug”. Onto the rest of the very long menu!

menu method

Now we have another condition, the “if” condition. So now we have if input.to_i > 0 which means the result of the string will be returned as a integer; so if the user’s input of characters used is more than 0, it continues forward with the code. I then create a variable named doggo and have it assigned with an instance called dogs[input.to_i-1] and then used doggo in a string with puts “#{doggo.breed} which is has it call upon the instance and grabbing the keyword breed from it and displaying it for the user as such:

Pug Bio thanks to Purina!

The elsif is a condition ran after the if condition. So with the input from user the program will create a condition to see if it matches anything from the method. For example if a condition was met, it will display a method as a result.

Let’s say the user types in a string: “Pug”. The program will skip the American Eskimo Dog and it’s result(eskimo_bio) and then land with “pug” and give the user the result “pug_bio” method. The result is in the picture above.

menu method (example of elsif condition)

For the method called pug_bio, we’re going to dissect it. See whats going on.

pug_bio method

At face value, we see an instance, an if statement, and an iterator being used. Lets start with the string, puts “Pug Bio” creates a string for the user to see the words “Pug Bio” as a title for the biography. The instance method I created was dogs once again; I set the dogs instance with the DogBio file and grabbing the list. Now using the dogs instance, we iterate through it with select along with_index(1), within the iteration we then use an if statement where if the index matches to 2, we then return a string matching the index and bringing the dog.bio to the user. But right before we have it sent, I decided to slice out the index, which means the user will not receive a index number with the bio, but only the bio. So .slice(“#{dog.bio}”) returns the user only the bio. There however is an easier way of returning just the bio. As I was writing this post, I decided to refactor my code a little bit and instead of using slice and matching the index within the string, we could instead just use puts “#{dog.bio}” to return the pug bio to the user.

Result of refactoring code. Still Works!

All of the bio methods have about the same type of coding style so it pattern matches a little bit which i’m not too happy about, but hey! It’s an MVP for now!

The dog_bio.rb is where all of the magic has been happening for my CLI to be working properly and where I’ve been getting all this information parsed from. Starting off with the class method self.list:

list and scrape_dogs class methods

self.list is a class method that call upon another class method that in fact! calls upon other class methods. Thats a lot of methods being called upon another. So whats going on in scrape_dogs? I created an empty array named dogs, I then have it shoveled in by multiple methods and finally being called once again with all the other methods in it. So now the empty array is no longer empty! It holds all of the other methods in a list. Now for the methods being put in the array.

Class methods scraping information from Purina

Each one of these methods are parsing information using Nokogiri, scraping information from the website and being put into my application. doc is being set to Nokogiri::HTML and opening the website address. Doggo is being used to create a new id, then we use doggo to set it up with a breed using .breed and having it parsed in with doc.search to search through the website for specific details and then having it put into text using .text. We later do the same thing with bio and then at the very end we call upon doggo so we have a finished product. Think of it as an assembly line, we need certain information put into our final product so we take turns putting something new in and then call upon it when its finished!

Finally when we have everything set up, we go into our bin folder and have Dog::CLI.new.call.

Runs the program

With this in our dog file, we call upon it in terminal where it starts the program and then goes ahead an grabs the call method that we have in our cli file.

call method

With that, we’ve made it back to where we started. How I approached this task. It took some time to make and even moreI should say attempting to explain it on paper into actual English! It was a big struggle making sure everything worked. A big tip that was given to me was “ALWAYS TEST YOUR CODE! EVEN IF IT’S THE SMALLEST CHANGE, TEST!” I now always test my code no matter the change.

Thanks!

Thank you for reading and hope that anything I published will help you! Remember to test your code!