初めに
初めまして。Jintaと申します。
個人開発をするにあたって、GooglePlacesAPIから取得したデータをデータベースに保存することがあったので、同じような状況の方のために、記録として残します。
テーブルの作成
まず、取得したデータを保存するテーブルを作成します。
GooglePlacesAPIから取得できるデータは、一部ですが記事にまとめたのでこちらをご覧ください。
Google Places APIを使用して情報を取得(Rails)
テーブルの作成(マイグレーションファイル)
2023083120000_create_shops.rb
class CreateShops < ActiveRecord::Migration[7.0]
def change
create_table :shops do |t|
t.string :name, null: false #店名
t.string :postal_code #郵便番号
t.string :address #住所
t.string :phone_number #電話番号
t.string :opening_hours #営業時間
t.string :web_site #ウェブサイト
t.decimal :latitude, precision: 10, scale: 7, null: false #緯度
t.decimal :longitude, precision: 10, scale: 7, null: false #経度
t.string :place_id, null: false #プレイスID
t.timestamps
end
end
end
bin/rails db:migrate
取得したいデータの情報をcsvファイルに書き出す
情報を取得する流れとして、
取得したいショップの電話番号(国際番号)をcsvファイルにまとめる→電話番号(国際番号)からplace_idを取得する→取得したplace_idから必要な詳細情報を取得する。
なので、csvファイルに取得したいショップの電話番号を書き出します。
csvファイルは以下の通り
lib/cafe.csv
都道府県,店名,電話番号
東京,STARBUCKS RESERVE® ROASTERY TOKYO,+81 3-6417-0202
rakeタスクでデータベースへの保存処理を実行する
lib/tasks/get_cafe_shop_details.rake
require 'csv' #csvファイルを操作するライブラリの読み込み
require 'open-uri' #open-uriライブラリを読み込んでいる
API_KEY = ENV['API_KEY'] #.envに記述しているAPIキーを代入
namespace :Cafe do
desc 'Fetch and save shop details'
task :get_and_save_details => :environment do
#電話番号からplace_idを取得するメソッド
def get_place_id(phone_number)
client = GooglePlaces::Client.new(API_KEY)
spot = client.spots_by_query(phone_number).first
spot.place_id if spot
end
#place_idから詳細情報を取得するメソッド
def get_detail_data(shop)
place_id = get_place_id(shop['電話番号'])
if place_id
#クエリーパラメータの作成
place_detail_query = URI.encode_www_form(
place_id: place_id,
language: 'ja',
key: API_KEY
)
#PlacesAPIのエンドポイントの作成
place_detail_url = "https://maps.googleapis.com/maps/api/place/details/json?#{place_detail_query}"
#APIから取得したデータをテキストデータ(JSON形式)で取得し、変数に格納
place_detail_page = URI.open(place_detail_url).read
#JSON形式のデータを、Rubyオブジェクトに変換
place_detail_data = JSON.parse(place_detail_page)
#取得したデータを保存するカラム名と同じキー名で、ハッシュ(result)に保存
result = {}
result[:name] = shop['店名']
result[:postal_code] = place_detail_data['result']['address_components'].find { |c| c['types'].include?('postal_code') }&.fetch('long_name', nil)
full_address = place_detail_data['result']['formatted_address']
result[:address] = full_address.sub(/\A[^ ]+/, '')
result[:phone_number] = place_detail_data['result']['formatted_phone_number']
result[:opening_hours] = place_detail_data['result']['opening_hours']['weekday_text'].join("\n") if place_detail_data['result']['opening_hours'].present?
result[:web_site] = place_details_data['result']['website']
result[:latitude] = place_detail_data['result']['geometry']['location']['lat']
result[:longitude] = place_detail_data['result']['geometry']['location']['lng']
result[:place_id] = place_id
result[:web_site] = place_detail_data['result']['website']
result
else
puts "詳細情報が見つかりませんでした。"
nil
end
end
#csvファイルを読み込む
csv_file = 'lib/cafe.csv'
#csvファイルの繰り返し処理で実行しデータベースへ保存
CSV.foreach(csv_file, headers: true) do |row|
shop_data = get_detail_data(row)
if shop_data
shop = Shop.create!(shop_data)
puts "#{row['店名']}を保存しました"
puts "----------"
else
puts "#{row['店名']}の保存に失敗しました"
end
end
end
end
終わりに
初めてAPIを使用したので、割と時間がかかってしまいましたが、正常に保存ができて良かったです。
個人開発で発見のあった事は、なるべく記事にしていきたいと思います。
最後までご覧いただきありがとうございました。