LoginSignup
0
0

緯度経度から天気予報を取得し投稿詳細画面に表示する

Last updated at Posted at 2023-11-09

1.はじめに

ポートフォリオに天気予報を追加したので、知識の定着、復習のために記事を書きます。
この記事を、ご覧いだだくことで緯度経度から天気予報を取得し表示できます。

2.環境

Ruby (2.6.4)
Rails (6.1.7)

3.前提条件

4.実装

1.gemhttpartyを導入する

  • HTTPartyを使用するために、Gemfile に gem 'httparty' を追加してください。
  • その後ターミナルでbundle installを実行してGemをインストールしてください。
Gemfile
gem 'httparty'

2.緯度経度から天気予報の情報を取得する

class PostsController < ApplicationController
  require 'httparty' # ①

  def show # ②
    @weather_data = get_weather_forecast(@post.latitude, @post.longitude)
  end

  private

  def get_weather_forecast(latitude, longitude)
    api_key = ENV['OPENWEATHERMAP_API_KEY'] # ③
    api_url = "https://api.openweathermap.org/data/2.5/forecast?lat=#{latitude}&lon=#{longitude}&appid=#{api_key}&lang=ja&units=metric" # ④
    response = HTTParty.get(api_url) # ⑤
    weather_data = JSON.parse(response.body) # ⑥
    return weather_data # ⑦
  end
end

require 'httparty'は、HTTPartyをアプリケーション内で使用するための記述です。

②showアクションでget_weather_forecastメソッド(後述します)を呼び出しています。

  • 引数には投稿された情報(緯度、経度)を渡しており、OpenWeatherMapAPIから天気予報データを取得します。
  • 取得したデータは@weather_dataに格納され、後ほどビューで使用します。

api_key = ENV['OPENWEATHERMAP_API_KEY']でAPIキーを取得しています。
APIキーは環境変数で設定しています。

api_url = "https://api.openweathermap.org/data/2.5/forecast?lat=#{latitude}&lon=#{longitude}&appid=#{api_key}&lang=ja&units=metric"でAPIリクエストのURLを構築しています。

  • latとlonは引数として与えられた緯度と経度です。
  • appidにはAPIキーが、langには言語(日本語)、unitsには温度の単位(摂氏)を指定しています。

⑤- response = HTTParty.get(api_url)でHTTPartyを使用して、構築したAPIリクエストを発行し、APIからのレスポンスを取得しています。

weather_data = JSON.parse(response.body)でJSON.parseメソッドを使用してJSONをRubyのハッシュに変換しています。

  • JSON.parseメソッドとは(簡単に)
    「JSONデータ」は、単純なテキストデータであり文字列でもあります。そのためプログラムで利用しやすい形式に変換する必要があります。それを実現してくれるのが「JSON.parse()」メソッドです。

return weather_data変換された天気予報データを呼び出し元に返します。

3.viewの記述

        <% if @weather_data.present? %> # ①
        <h2>5日間の天気予報</h2>
        <% daily_forecasts = @weather_data['list'].group_by { |forecast| Time.at(forecast['dt']).strftime('%Y-%m-%d') } %> # ②
          <% daily_forecasts.each do |date, forecasts| %> # ③
              <% forecasts.each do |forecast| %> # ④
              <% if Time.at(forecast['dt']).hour == 12 %>
                <p><strong><%= Time.at(forecast['dt']).strftime('%m-%d %H:%M') %></strong></p>
                <p>気温: <%= forecast['main']['temp'].to_i %>度</p>
                <p>天気: <%= forecast['weather'][0]['description'] %></p>
                <img src="https://openweathermap.org/img/wn/<%= forecast['weather'][0]['icon'].gsub('n', 'd') %>@2x.png" alt="Weather Icon">
                <% if forecast['rain'].present? && forecast['rain']['3h'].present? %>
                <p>降水確率: <%= forecast['rain']['3h'] %>mm</p>
                <% else %>
                <p>降水確率: 0mm</p>
                <% end %>
              <% end %>
              <% end %>
          <% end %>
        <% else %> # ⑤
        <p>天気情報が取得できませんでした。</p>
        <% end %>

<% if @weather_data.present? %>

  • @weather_dataが存在するかどうかを確認しています。
  • 存在する場合は天気予報を表示し、存在しない場合はエラーメッセージを表示します。

daily_forecasts = @weather_data['list'].group_by { |forecast| Time.at(forecast['dt']).strftime('%Y-%m-%d') }

  • group_byメソッドを使用して、@weather_data['list']内の天気予報データを日付ごとにグループ化しています。
  • Time.at(forecast['dt']) は、UNIXタイムスタンプをRubyのTimeオブジェクトに変換しています。
  • strftime('%Y-%m-%d') は、Timeオブジェクトを年-月-日の形式に変換しています。

<% daily_forecasts.each do |date, forecasts| %>

  • daily_forecastsハッシュから日付とその日付に対応する予報データの配列を取り出して、それを元にループを行います。
  • このループは、日付ごとの予報データを処理するためのもので、dateには日付(キー)が、forecastsにはその日付に対応する予報データの配列(値)が入ります。

<% forecasts.each do |forecast| %>

  • 各日付ごとの予報データの配列(forecasts)を処理するためのループです。

  • <% if Time.at(forecast['dt']).hour == 12 %>は、その中で各予報データの時間が12時のものだけを選別する条件文です。ここでは、12時の予報データだけを表示しています。

  • その後、データに対して以下の情報を表示しています

  • 予報の日時(<%= Time.at(forecast['dt']).strftime('%m-%d %H:%M') %>)

  • 気温(<p>気温: <%= forecast['main']['temp'].to_i %>度</p>)

  • 天気の説明(<p>天気: <%= forecast['weather'][0]['description'] %></p>)

  • 天気のアイコン(<img src="https://openweathermap.org/img/wn/<%= forecast['weather'][0]['icon'].gsub('n', 'd') %>@2x.png" alt="Weather Icon">)
    gsub('n', 'd')で、取得したアイコンの文字列が'n'(夜のアイコン)の場合に'd'(昼のアイコン)に置き換えています。これにより、常時昼間のアイコンを表示させることができます。

  • <% if forecast['rain'].present? && forecast['rain']['3h'].present? %>は、予報データに雨が含まれており、かつ3時間降水量のデータが存在する場合に、降水確率を表示しています。

@weather_dataが存在しない場合はエラーメッセージを表示します。

5.おわりに

以上で緯度経度から天気予報を取得できるようになります。
意外と簡単に実装できるので実装したいと思っている方はぜひチャレンジしてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0