CLI Ruby gem with Dark Sky API

EclecticCoder
5 min readOct 5, 2019

--

Photo by Jake Gard on Unsplash

This week I finished my first project at Flatiron School. I was tasked with designing a Ruby Gem with a Command Line Interface (CLI), which met the following requirements:

  • Provide data from an external web site using scraping or an external API
  • Data must go one level deep allowing user to make a choice to view more details of the data
  • Use good OO design patterns

I decided to design a weather app which would allow the user to retrieve the current conditions of a selected city, extended forecast, and/or a detailed forecast of a specified day. This type of data is not conducive to scraping technologies like the gem Nokogiri, for instance. for example, a search for the weather in Washington DC on AccuWeather yields a URL like this:

`https://www.accuweather.com/en/us/washington/20006/weather-forecast/327659`

This is a mashing of URL + Lang + Country + city +Postal Code +weather-forecast- + a random number.

Because of these difficulties I decided to use an external API called Dark Sky, which returns JSON data and is more easily managed in Ruby. This was a new journey for me and I had to read and teach myself about API’s.

This article will be structured in the following way:

  • Showing the UI design of a CLI
  • Explaining the applications logic 💭
  • Focusing on a AHA 💡moment
  • Finally a TODO list of additional features for the future

TLTR: Get the code from here Weather Ferret

Image by Mudassar Iqbal from Pixabay

User Interface

The CLI can honestly be boring by today’s graphical standards. So, designing the interface included ways to make the data standout. So I used the command called figlet to make a banner for the application. Figlet is available via Homebrew on or via your package manager in Linux. Using the following command:

figlet -f slant “Weather Ferret”

gave me a nice banner:

Next I used a gem called colorize, to accent the questions to the user and make headers stand out:

I also used colorize to make the Error messages stand out:

Connecting With API x 2

So, the user inputs a location. Great! 🎊 The bad news, Dark Sky API does not accept location names 😢 So the first task is to convert the entered location name to Geodetic coordinates. Using the Ruby gem Geocoder, according to the documentation, “Connects to more than 40 APIs worldwide.” In turn, Geocoder takes the location name and we can retrieve the coordinates which Dark Sky requires.

Notice it is literally one line of code, the rest is for the configuration we need later.

To access the Dark Sky API, we use a gem called forecast_io, which is a wrapper for the API. So, piecing this together, within the Request class, there are two methods: fetch and coordinate_pts. As you can see, coordinate_pts is called from fetch

When the user enters valid data, two lists are displayed: Current Condition and a brief extended forecast. The Current Conditions are initiated from the Forecast class:

The request method is called and the resulting forecast is retrieved and stored in an instance variable that can be used throughout to extract the relevant data. For instance, each section of the table uses the method fetch_curr_data which used the instance variable. The result for the user:

Notice how the UI is displayed. The titles of each section, the question, and prompt after the data is accented with colorize. Also, the numbers for each line of the Extended Forecast section are accented as well.

The user can decide to EXIT the application or look at more details of a specific days weather.

In each of the screens, keeping with the UI theme, two gems from the TTY Toolkit are utilized. The first is a spinner which loads as the API is returning data, but in both of the screenshots presented, the data is presented using TTY-Table, which provides the developer a “flexible and intuitive table formatting” environment. This allows for data presented in the UI to draw the users attention to the requested data.

Photo by Ben White on Unsplash

AHA Moment

Developing this project was challenging as I started to apply what I had been learning but the biggest AHA moment was in method abstraction. The plan was to develop a Forecast class which would contain multiple single purpose methods for each weather condition. As I coded these methods I realized, other than the method name, the only other difference was one hash key. The below methods were for the Detailed Extended Forecast:

Sure this is okay, after all it works, but it is not efficient. I decided to create a new method that used a string argument. By creating the below two methods, one for current forecast and the second for the detailed extended forecast, it eliminated eight methods.

TODO List

This application was a joy to work on and I learned a lot. So in the spirit of no program is ever really finished, I am maintaining a running list of features and enhancements I wish to add:

  1. Add caching to `Geocoder` to limit the amount of API calls to convert locations to coordinates.
  2. Add custom weather emoji's based on the `icon` field from `Dark Sky API`.
  3. Add settings feature to handle units instead of hard coding them (i.e. mph vs. kmp, F vs. C)
  4. Add caching to `Forecast_IO`

Thank you for reading and you may also like to read my recent article:

--

--