Weather for Dummies & POODR

Don't you hate when you rush to leave for work in the morning, only to discover upon leaving your building that it is much too cold/wet/hot/dry to the outfit you thoughtlessly chose that day? Or maybe, like a good friend of mine (we'll call him Noah, because that's his name), you just have no idea how to dress yourself appropriately for the weather.

Now, with the help of Weather for Dummies, a simple command line app, you'll never have to worry about that again! Just run my Weather for Dummies app in the command line of your computer, and you'll be informed of the current weather and be given some suggestions of appropriate clothing and/or outer-wear.

This past week at Flatiron has introduced us to the concept of Object Oriented Design. Instead of only focusing on the task at hand, (how to get each discrete piece of my program to work, for example), I've begun thinking about my code as something that is alive, something with the ability to grow. This means that my programs shouldn't just be designed to work right now, but should accommodate future change and functionality. Reading up on the principles behind SOLID programming and learning more about the work of Sandi Metz and practical object oriented design (POOD) has really helped.

A few take-aways that informed my (very simple) Weather for Dummies design:

-Classes should have one, single responsibility.

-Methods should have a single responsibility.

With this in mind, I set to work designing Weather for Dummies.

I began with a question: What does Weather for Dummies actually do? It was a tough question to answer, because Weather for Dummies didn't exist at this point, but I used my imagination.

-Weather for Dummies need to inform a user of the current weather conditions and make some clothing recommendations based on those conditions.

This led me to another question: What does Weather for Dummies need in order to fulfill that purpose?

-It needs to access some weather conditions, decide what kind of outfits to recommend based on that info and interact with the user to get their location and inform them of the weather/outfits.

The different jobs described above corresponded loosely to my different classes and overall file structure.
alt

The lib directory holds all of the classes (including a neat little DIY console constructed using bash and pry!), and the bin directory holds the executable CLI.

Let's take a closer look inside these classes. To make my thought process more transparent, we'll organize this walk-through in terms of the tasks the app must accomplish.

Get weather conditions: the Forecast class

To get some weather without looking outside my window (who wants to look away from the computer screen anyway, am I right?), I used JSON, together with the wunderground weather api.

class Forecast

  BASE_URL = "http://api.wunderground.com/api/e3aedba0b8b8d5e5/conditions/q"

  def get_url(state, city)
    "#{BASE_URL}/#{state}/#{city}.json"
  end
  
  def get_json(url)
    JSON.load(open(url))
  end

JSON objects are essentially hashes of data. In this case, when Ruby executes JSON.load(open(url)), a hash of weather data from the wunderground api is born. To access certain elements of that hash (temperature and percipitation), I examined it using the console I built and played around with accessing it's key/value pairs until I had the formula for extracting the data I needed. I then encapsulated those formulas in two different methods. One for getting the temperature and one for checking for percipitation (remember--each method should have just one responsibility!):

def get_current_temp(weather_hash)
    temp = weather_hash["current_observation"]["temp_f"]
    if temp <= 32
      "cold"
    elsif (33..50).include?(temp)
      "cold-ish"
    elsif (51..65).include?(temp)
      "generally pleasant"
    elsif (65..75).include?(temp)
      "warm"
    else 
      "hot"
    end
  end

  def percipitating?(weather_hash)
    true
    percipitation = weather_hash["current_observation"]["weather"]
    if percipitation.scan(/(Rain|Snow|Hail|Sleet)/).flatten[0] != nil
      return true
    else
      return false
    end
  end 

And that's it for the Forecast class!

Make some outfit recommendations depending on the weather forecast: the GetDressed class

GetDressed needs to know what the weather is, so it has a method that instantiates a new instance of the Forecast class and uses that forecast to tell you what to wear.

GetDressed also has a call method so that the CLI class can instantiate GetDressed and call .call on it to achieve a weather forecast plus outfit recommendation, all in one go.

Talk to the user and report the weather and outfit for the day: the CLI class

The CLI is responsible for welcoming the user and asking them for their location:


def welcome
    puts "Hey Noah. Don't worry, I'll tell you exactly what to wear today--you don't even have to look out of your window."
  end

  def get_location
    puts "What state are you in?"
    @state = gets.strip
    puts "What city are you in?"
    @city = gets.strip.gsub(" ", "_")
  end 

Then, the class' run method boots up an instance of GetDressed, which gets the forecast for us and generates some appropriate recommendations.

GetDressed.new.call

ta-da!

alt

If you want to use Weather for Dummies, check it out on github.

subscribe and never miss a post!

Blog Logo

Sophie DeBenedetto

comments powered by Disqus
comments powered by Disqus