はじめに
※この記事は、『RUNTEQ Advent Calendar 2023』の20日目に参加しております。
今回、個人開発のアプリを作成するにあたり、初めてAPIを叩いてみました。
「OpenWeatherMap API」を使用して、ローカル開発環境にてAPIお試し用のアプリを作成し、情報を取得するまでの一連の流れについてまとめました。
そもそもAPIとは何なのか?という部分も曖昧だったので、こちらの記事にまとめております。
今回のゴール
フォームに都市名を入力し、検索ボタンを押すと気象データが表示されるようにする。
注意点
私はプログラミング学習中で、初学者です。
内容に誤りがある場合がございます。
もし間違いがあればご指摘いただけますと幸いです。
OpenWeatherMapとは?
OpenWeatherMapは、世界各地の過去、現在、予測の各種気象データの無料APIを提供するオンラインサービスです。
天気以外にも、温度、湿度、風速など、さまざまな情報を取得できます。
事前準備
- OpenWeatherMapにアカウントを作成
- APIキーを取得
アカウントを作成し、マイページのMy API keys
を開くと、キーが表示されます。
テスト用のRailsアプリケーションを作成
rails new apitest
cd apitest
必要なgemをインストール
httparty
とdotenv-rails
というgem
をインストールします。
gem 'httparty'
gem 'dotenv-rails', groups: [:development, :test]
bundle install
httpartyについて
httparty
は、Rails
でAPIを叩く際に使用されるgem
です。
【特徴】
-
HTTP
リクエストを送信するための簡潔で読みやすい構文を提供している -
GET
、POST
、PUT
、DELETE
など、さまざまなHTTP
メソッドをサポートしているため、あらゆる種類のAPIと簡単に連携できる -
JSON
形式のデータの扱いに優れている - APIからの応答を簡単に解析し、
Ruby
オブジェクトとして扱うことができるため、応答データの処理が容易になる -
HTTP
リクエストが失敗した場合のエラーハンドリング機能も備わっているため、エラー状況をより効果的に処理できる
dotenv-railsについて
dotenv-rails
は、Rails
で環境変数を管理することができるgem
です。
【特徴】
-
.env
ファイルを使用して、環境変数を簡単に設定し管理することができるため、開発環境やテスト環境での構成が容易になる - ローカル開発環境において、データベースの接続情報や外部APIのキーなどの機密情報を、安全に管理するための簡単な方法を提供している
- Railsアプリケーションが起動する際に、自動的に
.env
ファイルを読み込み、環境変数をRailsの環境にマージする - 環境ごと(例えば
.env.development
、.env.test
)に異なる.env
ファイルを使用することができ、環境固有の設定を管理しやすくなる
config/credentials.yml.encを使用する方法もある
機密情報(今回の場合はAPIキー)を保存する方法として、Rails 5.2以降ではconfig/credentials.yml.enc
ファイルを使用する方法もあり、どちらを選ぶべきなのかChatGPT先生に聞いてみたところ、
- セキュリティが最優先の場合、またはチームメンバー間で機密情報を共有する必要がある場合は、config/credentials.yml.enc が適しています。
- 開発の柔軟性や環境設定の簡略化を優先する場合、または個々の開発者が独自の設定を持つ必要がある場合は、.env ファイルが便利です。
とのことで、今回は.env
ファイルを使用したのですが、間違いがありましたらご指摘いただけますと幸いです。
環境変数を定義
プロジェクトのルートディレクトリに.env
ファイルを作成し、環境変数を定義します。
OPENWEATHERMAP_API_KEY = "取得したAPIキーをここに記述"
次に.gitignore
ファイルに /.env
を追加します。
/.env
.gitignore
ファイルに記述することで、.env
ファイルがGit
によるバージョン管理から除外され、GitHub
に機密情報が誤ってcommit
されることを防ぎます。
APIを叩いてみる
「APIを叩く」という言い回しは、指定されたAPIのエンドポイント(URL)に対して、特定のHTTP
メソッド(GET
、POST
、PUT
、DELETE
など)を使用してリクエストを行うことを意味します。
https://api.openweathermap.org/data/2.5/weather?q=kawasaki,jp&appid={API key}&lang=ja
HTTP
リクエストを送ると、多くのAPIではJSON形式でレスポンスが返ってくるため、必要なデータだけを抽出し、数値を加工して見やすくしていきたいと思います。
{
"coord":{
"lon":139.7172,"lat":35.5206
},
"weather":[
{
"id":500,
"main":"Rain",
"description":"小雨",
"icon":"10n"
}
],
"base":"stations",
"main":{
"temp":283.51,
"feels_like":282.43,
"temp_min":282.08,
"temp_max":285.38,
"pressure":1023,
"humidity":70
},
"visibility":10000,
"wind":{
"speed":3.09,
"deg":340
},
"rain":{
"1h":0.13
},
"clouds":{
"all":75
},
"dt":1702572846,
"sys":{
"type":1,"id":8074,"country":"JP","sunrise":1702590161,"sunset":1702625355
},
"timezone":32400,
"id":1859642,
"name":"川崎市",
"cod":200
}
ルーティング
Rails.application.routes.draw do
get 'weather', to: 'weather#index', as: :weather
get 'weather/show', to: 'weather#show', as: :show_weather
end
コントローラ
# gem httpartyを読み込む
require 'httparty'
# URIモジュールを読み込む(URLのエンコードや解析に使われる)
require 'uri'
class WeatherController < ApplicationController
before_action :validate_city, only: [:show]
def index
end
def show
# WeatherServiceのインスタンスを生成し、fetch_weatherメソッドを呼び出して天気情報を取得
response = WeatherService.new(params[:city]).fetch_weather
# HTTPレスポンスが成功かどうかをチェック
if response.success?
# HTTParty からのレスポンスをパースして、Rubyのハッシュ形式のデータ構造(weather_data)に変換
weather_data = response.parsed_response
@weather = {
# 取得したweather_dataハッシュから特定の気象データを取り出し、適切な形式に変換
name: weather_data["name"],
temp_celsius: kelvin_to_celsius(weather_data["main"]["temp"]).round(2),
feels_like_celsius: kelvin_to_celsius(weather_data["main"]["feels_like"]).round(2),
temp_min_celsius: kelvin_to_celsius(weather_data["main"]["temp_min"]).round(2),
temp_max_celsius: kelvin_to_celsius(weather_data["main"]["temp_max"]).round(2),
humidity: weather_data["main"]["humidity"],
wind_speed: weather_data["wind"]["speed"],
description: weather_data["weather"][0]["description"]
}
else
# 成功でない場合、ユーザーをindexアクションにリダイレクトし、エラーメッセージを表示
redirect_to action: :index, alert: "天気情報の取得に失敗しました。"
end
end
private
def validate_city
# 都市名が空であれば、ユーザーをindexアクションにリダイレクトし、警告メッセージを表示
redirect_to(action: :index, alert: "都市名を入力してください。") if params[:city].blank?
end
# ケルビン単位の温度を摂氏単位に変換するkelvin_to_celsiusメソッドを定義
def kelvin_to_celsius(kelvin)
kelvin - 273.15
end
end
class WeatherService
# HTTPartyモジュールをWeatherServiceクラスにインクルード
include HTTParty
# OpenWeatherMap APIのベースURIを設定
base_uri 'api.openweathermap.org'
def initialize(city)
# 環境変数からOpenWeatherMapのAPIキーを取得
api_key = ENV['OPENWEATHERMAP_API_KEY']
# APIリクエストのためのオプションを設定
@options = { query: { q: "#{city},jp", appid: api_key, lang: 'ja' } }
end
def fetch_weather
# HTTPartyによって提供されるgetメソッドをクラスメソッドとして呼び出す
self.class.get("/data/2.5/weather", @options)
end
end
-
.round(2)
は温度を小数点以下2桁まで表示させるために使用 - 摂氏温度はケルビン温度から273.15を引くことで計算
ビュー
<%= form_with url: show_weather_path, method: :get do |form| %>
<%= form.label :city, "都市名:" %>
<%= form.text_field :city %>
<%= form.submit "検索" %>
<% end %>
<h1><%= @weather[:name] %> の天気</h1>
<p><strong>温度:</strong> <%= @weather[:temp_celsius] %> °C</p>
<p><strong>体感温度:</strong> <%= @weather[:feels_like_celsius] %> °C</p>
<p><strong>最低温度:</strong> <%= @weather[:temp_min_celsius] %> °C</p>
<p><strong>最高温度:</strong> <%= @weather[:temp_max_celsius] %> °C</p>
<p><strong>湿度:</strong> <%= @weather[:humidity] %> %</p>
<p><strong>風速:</strong> <%= @weather[:wind_speed] %> m/s</p>
<p><strong>天気:</strong> <%= @weather[:description] %></p>
<div>
<%= link_to '戻る', weather_path, class: "btn btn-primary" %>
</div>
完成!
都市名を入力し、検索ボタンを押すと気象データが表示されるようになりました。
無料プランの場合、1分間に60回APIを呼び出せるそうです。
まとめ
初めてAPIを叩いてみましたが、OpenWeatherMap APIは無料プランでもさまざまな情報を取得でき、とても便利だなと感じました。これから個人開発を始めるため、APIを活用してより良いアプリを作っていけたらいいなと思います。
最後まで読んでくださりありがとうございました!