Display weather forecast using OpenWeatherMap, an external API in Ruby

App description

It is a program that displays the weather forecast for the next day with Ruby. Use ʻOpenWeatherMap` in the external API.

Development environment

ruby:2.6.6

Complete image

wf.gif

Operation flow
  1. Execute ruby execution.rb in the root directory of the app.
  2. The prefectures are listed.
  3. Enter the prefecture number.
  4. The weather forecast for the next day is divided every 3 hours and displayed in a list.

Directory configuration diagram

wf.png

OpenWeatherMap API key required in advance

To create this program, you will need the ʻAPI key of ʻOpenWeatherMap.

  1. Click Account Registration from the ʻOpenWeatherMap` homepage.
  2. An email will be sent to the registered email address.
  3. The ʻAPI key` is included in the body of the received email, so use this.

Store API key in environment variable

As a security measure, store the ʻAPI key` in an environment variable that cannot be referenced from the outside.

Method of operation

Terminal


vim ~/.zshrc

Set to insert mode and add the following.

.zshrc


export WEATHER_API_KEY="Enter API key"

Finish saving with : wq, execute the following to reflect the settings.

Terminal


source ~/.zshrc

Allow API keys to be used in code

Create a config.rb file and add the following.

config.rb


WEATHER_API_KEY = ENV["WEATHER_API_KEY"]

This time, we will substitute it for a constant and use it. You can now use the ʻAPI key with the constant name WEATHER_API_KEY`.

Create and load a CSV file of the prefecture list

Create a prefectures.csv file and add the following prefecture list.

prefectures.csv


prefecture,english
Hokkaido,Hokkaido
Aomori Prefecture,Aomori-ken
Iwate Prefecture,Iwate-ken
Miyagi Prefecture,Miyagi-ken
Akita,Akita-ken
Yamagata Prefecture,Yamagata-ken
Fukushima Prefecture,Fukushima-ken
Ibaraki Prefecture,Ibaraki-ken
Tochigi Prefecture,Tochigi-ken
Gunma Prefecture,Gunma-ken
Saitama,Saitama-ken
Chiba,Chiba-ken
Tokyo,Tokyo
Kanagawa Prefecture,Kanagawa-ken
Niigata Prefecture,Niigata-ken
Toyama Prefecture,Toyama-ken
Ishikawa Prefecture,Ishikawa-ken
Fukui prefecture,Fukui-ken
Yamanashi Prefecture,Yamanashi-ken
Nagano Prefecture,Nagano-ken
Gifu Prefecture,Gifu-ken
Shizuoka Prefecture,Shizuoka-ken
Aichi prefecture,Aichi-ken
Mie Prefecture,Mie-ken
Shiga Prefecture,Shiga-ken
Kyoto,Kyoto Prefecture
Osaka,Osaka-fu
Hyogo prefecture,hyogo
Nara Prefecture,Nara-ken
Wakayama Prefecture,Wakayama-ken
Tottori prefecture,Tottori-ken
Shimane Prefecture,Shimane-ken
Okayama Prefecture,Okayama-ken
Hiroshima Prefecture,Hiroshima-ken
Yamaguchi Prefecture,Yamaguchi-ken
Tokushima Prefecture,Tokushima-ken
Kagawa Prefecture,Kagawa-ken
Ehime Prefecture,Ehime-ken
Kochi Prefecture,Kochi Prefecture
Fukuoka Prefecture,Fukuoka-ken
Saga Prefecture,Saga-ken
Nagasaki Prefecture,Nagasaki-ken
Kumamoto Prefecture,Kumamoto-ken
Oita Prefecture,Oita Prefecture
Miyazaki prefecture,Miyazaki-ken
Kagoshima prefecture,Kagoshima-ken
Okinawa Prefecture,Okinawa-ken

Read CSV file

Create ʻexecution.rb` and add the following.

execution.rb


require "csv"

prefectures = CSV.read("./prefectures.csv", headers: true)

Create WeatherInfo class

Create weather_info.rb and define the class.

weather_info.rb


class WeatherInfo
  def initialize(prefectures)
    @prefectures = prefectures
  end
end

Create an instance from the WeatherInfo class in ʻexecution.rb` and pass the CSV data

execution.rb


require "csv"

prefectures = CSV.read("./prefectures.csv", headers: true)

#---------Add the following---------

weather_info = WeatherInfo.new(prefectures)

#-----------So far-----------

Define a method that displays a list of prefectures and allows you to select a number

In the WeatherInfo class, define the ** select_prefecture method that allows you to list ** prefectures and select numbers.

weather_info.rb


class WeatherInfo
  def initialize(prefectures)
    @prefectures = prefectures
  end

  #---------Add the following---------

  def select_prefecture
    puts <<~TEXT
            ☀~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~☀
            ☁                              ☁
☂ Tomorrow's weather forecast ☂
            ☆                              ☆
            ☀~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~☀

          TEXT

    #List output with index number of prefecture list
    @prefectures.each.with_index(1) do |prefecture, i|
      puts "#{i.to_s.rjust(2)}. #{prefecture["prefecture"]}"
    end
    puts <<~TEXT
            
Display tomorrow's weather information every 3 hours.
Please enter the prefecture number.
          TEXT
    while true
      input = gets.to_i
      #Exit the method if the correct list number is entered
      if input.between?(1, @prefectures.count)
        return @prefectures[input - 1]
      else
        #If anything other than the list number is entered, an error will be displayed and a reloop will occur.
        puts <<~TEXT
                --------------------------------------------
error: Please enter only the displayed number.
                --------------------------------------------
              TEXT
      end
    end
  end

  #-----------So far-----------

end

--If the number of digits of the index number in the displayed prefecture list is different, it will not be aligned vertically. I'm using rjust (2) to convert it to a string with to_s to align it vertically. --When an index number other than the index number is entered, an error statement is displayed and a loop is made.

ʻExecute the select_prefecture method in execution.rb`

ʻExecute the select_prefecture method defined above in execution.rb. Also, read weather_info.rb`.

execution.rb


require "csv"

#---------Add the following---------

require_relative "weather_info"

#-----------So far-----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)

#---------Add the following---------

prefecture = weather_info.select_prefecture

#-----------So far-----------

Get weather information from OpenWeatherMap

Get the weather information from the external API ʻOpenWeatherMap. Define the get_weather_forecast method in weather_info.rb`.

weather_info.rb


class WeatherInfo
  #----------***Abbreviation***---------
  def select_prefecture
    #--------***Abbreviation***---------
  end

  #---------Add the following---------

  def get_weather_forecast(prefecture)
    #Get weather information from external API "OpenWeatherMap"
    response = open("http://api.openweathermap.org/data/2.5/forecast" + "?q=#{prefecture["english"]}&appid=#{WEATHER_API_KEY}&units=metric&lang=ja")
    #Analyze the acquired data as JSON
    data = JSON.parse(response.read)
    #Get only some information in JSON data and hash it
    datas = { list: data["list"], prefecture_name: data["city"]["name"] }
  end

  #-----------So far-----------
end
Specify the URL with the open method to get the weather information.

--http://api.openweathermap.org/data/2.5/forecast → You can get the weather forecast every 3 hours for 5 days. --? Q = → Enter the English city name of CSV data --& appid = → Enter API key --& units = metric → Specify the unit of data format --& lang = → Specify the language as Japanese

You can check the details of each parameter and JSON data at here.

ʻExecute the get_weather_forecast method in execution.rb`

ʻExecute the get_weather_forecast method defined above in execution.rb. Also, load the config.rb file, the json library, and the ʻopen-uri library.

execution.rb


require "csv"
require_relative "weather_info"

#---------Add the following---------

require_relative "config"
require "json"
require "open-uri"

#-----------So far-----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)
prefecture = weather_info.select_prefecture

#---------Add the following---------

datas = weather_info.get_weather_forecast(prefecture)

#-----------So far-----------

List the weather information for the next day

Define a display_weather_forecast method that lists the acquired weather information.

weather_info.rb


class WeatherInfo
  #----------***Abbreviation***---------
  def select_prefecture
    #--------***Abbreviation***---------
  end

  def get_weather_forecast(prefecture)
    #--------***Abbreviation***---------
  end

  #---------Add the following---------

  def display_weather_forecast(weathers)
    #Make it possible to display the day of the week in Japanese
    wd = ["Day", "Month", "fire", "water", "wood", "Money", "soil"]
    #next day
    tomorrow = Date.today + 1
    puts <<~TEXT


           ☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂

              #{weathers[:prefecture_name]}of#{tomorrow.strftime("%m/%d(#{wd[tomorrow.wday]})")}of天気予報   

           ☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂

         TEXT
    weathers[:list].each do |weather|
      #Convert to DateTime type
      date_and_time = DateTime.parse(weather["dt_txt"])
      #Date type is also available for comparison
      date = Date.parse(weather["dt_txt"])
      #List display only for the next day's information
      if date == tomorrow
        puts <<~TEXT
               ---------------------------
               #{date_and_time.strftime("%p%Around H")}
weather:#{weather["weather"][0]["description"]}
temperature:#{weather["main"]["temp"]}℃
               ---------------------------
             TEXT
      end
    end
  end

  #-----------So far-----------

end

ʻExecute the display_weather_forecast method in execution.rb`

ʻExecute the display_weather_forecast method defined above in execution.rb. Also, load the date` library.

execution.rb


require "csv"
require_relative "weather_info"
require_relative "config"
require "json"
require "open-uri"

#---------Add the following---------

require "date"

#-----------So far-----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)
prefecture = weather_info.select_prefecture
datas = weather_info.get_weather_forecast(prefecture)

#---------Add the following---------

weather_info.display_weather_forecast(datas)

#-----------So far-----------

Now that it's complete, the rest

Terminal


ruby execution.rb

If you execute, it will work according to the completed image.

Source code

https://github.com/keisuke-333/Weather_Forecast

Recommended Posts

Display weather forecast using OpenWeatherMap, an external API in Ruby
[Rails] How to display the weather forecast of the registered address in Japanese using OpenWeatherMap
[Ruby] Use an external API that returns JSON in HTTP request
Get weather forecast from OpenWeatherMap in Rails
[Ruby] Count an even number in an array using the even? Method
[Ruby] Searching for elements in an array using binary search
Display API definition in Swagger UI using Docker + Rails6 + apipie
Try using gRPC in Ruby
Achieve 3-digit delimited display in Ruby
Run an external process in Java
I tried using Elasticsearch API in Java
Map without using an array in java