My Very First CLI

Mariah Senior
3 min readDec 13, 2020

Creating a CLI for the first time was an interesting experience. Where I struggled most was in the very beginning of my project. After adding gems, and requiring the necessary files, it was time to start building classes & their methods. I chose to get the data I needed from the NYC Open Data API. The endpoint that I used had more info than needed, and I wasn’t sure how to extract and store that exact data to create an object. My cohort lead, Matteo, suggested I use mass assignment. Prior to my project, I only practiced using mass assignment once so I wasn’t exactly confident using this method.

Mass Assignment and Metaprogramming

Mass assignment allows us to take in a hash as an argument, and set its keys to a method name while its value is the value being passed to the method. Using this information, I created a hash with ONLY the data I wanted from the API, then used that same hash to initialize new RetailStore objects.

class API
URL = "https://data.cityofnewyork.us/resource/p6bh-gqsg.json"
def self.get_businesses
uri = URI.parse(URL)
response = Net::HTTP.get_response(uri)
businesses = JSON.parse(response.body)
businesses.each do |business|
if business["category"] == "Retail" type_business = BusinessType.find_or_create_by_type(business["type_of_business"])hash = {business_type: type_business, parsed_address: business["parsed_address"], city_state: business["city_state"],zip_code: business["zip_code"], phone_number: business["phone_number"], business: business["business"] }RetailStore.new(hash) end
end
end
end

In this method in the above snippet, I only wanted to retrieve from the API the businesses that are retail. For me to be able to use the data I retrieved in my API class, in my RetailStore class, I had to instantiate a RetailStore object with the hash I created. Now in the RetailStore class, the initialize method iterates over the hash using .each method. Since I wanted the method to create attributes for me, I called the attr_accessor method on the entire class which set key to method names and stored its value in value , and send method is what creates the methods for all of the attributes.

class RetailStore
def initialize(hash)
hash.each do |key, value|
self.class.attr_accessor key
self.send("#{key}=" , value)
end
self.class.all << self
end
end

When a RetailStore object is instantiated, it will have attributes for each key/value pair listed in the hash, only IF the instance itself has those attributes as well, and nothing more. So instead of hardcoding each attribute with an attr_accessor, I used mass assignment.

Using Gems

After creating all of the functionality desired in my CLI class, and making sure I met all requirements, I began to refactor my code and use the gems I added to alter the layout of my project.

Using the tty-prompt gem was pretty cool. I incorporated two of its methods into my CLI. One of which was used to create a paginated list of businesses that the user can choose from. The second one in the following method, prompt.yes?()returns a boolean after selection so I decided to use a ternary operator to give users the option to restart the program or exit it.

prompt.yes?("Would you like to choose a different store?".white)? repeat : goodbye

Upon completing my first CLI, I am satisfied. It wasn’t as hard as I thought it would be. It was definitely intimidating going from doing labs with tests, to building my own program without tests to guide me. With persistence, my basic knowledge and understanding of Ruby, the errors given in the terminal, and pry, I was able to successfully build my CLI.

--

--