LoginSignup
9
10

More than 3 years have passed since last update.

【Rails】Google Maps APIを利用して登録した住所をMap表示する

Last updated at Posted at 2021-01-28

目標

アプリケーションで登録した住所を元にgoogle mapを表示させる機能実装についてまとめます。
入力フォームに入力した住所から、詳細ページにてマップを表示、ピンを立てて位置表示させるまで実装します。
1.gif

開発環境

  • Ruby: 2.6.4
  • Rails: 5.2.4
  • OS: macOS Catalina

前提条件

  • 既に、住所を登録するためのテーブルおよびカラムは作成済みであること
    私は、音楽スタジオの口コミレビューサイトを作成しました。デモでは、スタジオを新規作成し、その詳細ページにマップ表示されるといったものです。
    本記事で登場する変数では下記を使用します。それぞれご自身の環境に合わせて書き換えてください。
    テーブル名:studios
    カラム名:address

Google Mapの機能を使うための準備

こちらに関してはこの記事内では省略します。以下の三点が準備出来ている前提で進めていきます。
参考にさせていただいた記事のリンクも貼っておきます。
1. APIキーを取得する
2. Maps JavaScript APIの有効化
 ↪https://qiita.com/matsubishi5/items/196fa1941da2152b6d5d
3. Geocoding APIの有効化
 ↪https://qiita.com/matsubishi5/items/1b784dbbe5f1c336ac70

緯度、経度を登録するためのカラムを用意

緯度(latitude)、経度(longitude)のカラムを追加します。
db/migrate/...マイグレーションファイルへの記述でカラムを追加します。

class AddDetailsToStudios < ActiveRecord::Migration[5.2]
  def change
    #住所(address)カラムは登録済み
    add_column :studios, :latitude, :float
    add_column :studios, :longitude, :float
  end
end

緯度、経度はfloat型にします。floatとは浮動小数点数型です。
難しい名前ですがざっくり言えば小数を扱える型です。
緯度、経度は小数点以下を含む数値によって表されるので、こちらの型にします。

記述したらrails db:migrateしてください。

Gemを導入する

Gemfile
gem 'gon'
gem 'geocoder'

gem 'gon'
 ↪コントローラーで定義したインスタンス変数を、viewのjavascript内で使用できるようにする
gem 'geocoder'
↪住所から緯度、経度を算出する

マップは、緯度と経度の情報を元に表示します。
geocoderは、登録した住所から緯度、経度を自動で算出してくれるいいヤツです。

記述したらbundle installしてください。

モデルの編集

次に、geocoderを使うために適用するモデルに以下の記述をします。
今回はスタジオの位置情報を表示したいので/app/models/studio.rbに記述しました。

studio.rb
class Studio < ApplicationRecord
  geocoded_by :address #追記
  after_validation :geocode, if: :address_changed? #追記

これでaddressを登録した際にgeocoderが緯度、経度のカラムにも自動的に値を入れてくれるようになります。

geocorderの設定ファイルを作成し、編集

今の状態でも、登録した住所から緯度、経度を算出してくれますが、
東京都渋谷区といった、大まかな住所までしか算出してくれません。

東京都渋谷区◯-◯◯-◯◯◯のような細かい位置まで算出するためにはどうすればよいでしょうか?

ここで活躍するのが、Geocoding APIです。
geocoderでもGoogle Map APIの情報源を使えるように設定すれば解決します。

configフォルダ内にgeocoder.rbファイルを作成します。

$ bin/rails g geocoder:config

ターミナルで上のコマンドを行うことによってconfig/initializers/geocoder.rbファイルができます。

作成されたファイルの中身を変更してgeocoderでgoogle mapのAPIを使って緯度、経度を検索できるようにします。

geocoder.rb
Geocoder.configure(
  # Geocoding options
  # timeout: 3,                 # geocoding service timeout (secs)
   lookup: :google,         # name of geocoding service (symbol)
  # ip_lookup: :ipinfo_io,      # name of IP address geocoding service (symbol)
  # language: :en,              # ISO-639 language code
   use_https: true,           # use HTTPS for lookup requests? (if supported)
  # http_proxy: nil,            # HTTP proxy server (user:pass@host:port)
  # https_proxy: nil,           # HTTPS proxy server (user:pass@host:port)
   api_key: ENV['GMAP_API'],               # API key for geocoding service
  # cache: nil,                 # cache object (must respond to #[], #[]=, and #del)
  # cache_prefix: 'geocoder:',  # prefix (string) to use for all cache keys

  # Exceptions that should not be rescued by default
  # (if you want to implement custom error handling);
  # supports SocketError and Timeout::Error
  # always_raise: [],

  # Calculation options
  # units: :mi,                 # :km for kilometers or :mi for miles
  # distances: :linear          # :spherical or :linear
)

これでGoogle Map APIを用いてgeocoderの精度をあげることができます。
より詳細な場所の指定ができるようになりました。

api_key: ENV['GMAP_API'],
APIキーは、他人に知られてしまうと悪用される危険性があります。
そこで、dotenv-railsというGemを使用して、geocoder.rbに直接APIキーを記入しないことでこの危険性を回避できます。

今回は、GMAP_API(私が命名しただけ)に、実際のAPIキーを格納しています。
geocoder.rb内にENV['GMAP_API']と記入することで、APIキーを渡すことができます。

詳細は、こちらの記事を参考にしました。記事の途中に出てきます。
https://qiita.com/matsubishi5/items/196fa1941da2152b6d5d#%E5%AE%9F%E8%A3%85

コントローラーの編集

studios_controller.rbを編集

studios_controller.rb
  def show
    @studio = Studio.find(params[:id])
    gon.studio = @studio #追記
  end

ビューを編集

application.html.erbを編集

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>StudioDig</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= include_gon %> #追記
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.9.0/css/all.css">
    <%= stylesheet_link_tag    'application', media: 'all' %>
    <%= javascript_include_tag 'application' %>

gonを読み込みます。
CSSとJavaScriptより先に読み込んでいる事に注意して下さい。

show.html.erbスタジオ詳細ページを編集

studios/show.html.erb
<div id="map"></div>


<script>
  let map;

  function initMap() {
    // geocoderを初期化
    geocoder = new google.maps.Geocoder()

    map = new google.maps.Map(document.getElementById('map'), {
      // コントローラーで定義した変数から緯度経度を呼び出し、マップの中心に表示
      center: {
        lat: gon.studio.latitude,
        lng: gon.studio.longitude
      },
      // マップの倍率はお好みで
      zoom: 17,
    });

    marker = new google.maps.Marker({
      // コントローラーで定義した変数から緯度経度を呼び出し、マーカーを立てる
      position: {
        lat: gon.studio.latitude,
        lng: gon.studio.longitude
      },
      map: map
    });
  }
</script>

<script async defer
      src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=<%= ENV['GMAP_API'] %>&callback=initMap">
</script>

<script async defer....</script>
これを記述しないと、マップが表示されません。忘れずに記述してください。

<%= ENV['GMAP_API'] %>
環境変数化したAPIキーです。
ビュー内で使う場合は、上記のように書きます。

CSS等で、高さの設定をしていないとマップが表示されません。忘れずに設定しておいてください。

application.scss
...
#map {
  height: 500px;
  width: 100%;
}
...

ハマったエラー

CLOUD9で開発していたために起こったエラーです。

上記のように、間違いなく実装しているのになぜか、Geocoding APIを利用すると緯度、経度を算出しなくなるエラーにハマりました。

Geocoding APIを利用しない設定(gemのgeocoderのみで算出する設定)にすると、緯度、経度が算出できます。(かなり大まかな住所しか特定しませんが..)

これは、Google Maps API自体の問題だろうと調べてみたところ、
HTTPリファラーの設定が問題だったようです。

HTTPリファラーとは、自分が設定したURL以外からのアクセスが出来ないようにする設定です。セキュリティ対策ですね。
例えば、http://localhost:3000/のアクセスを許可する場合、リファラーにlocalhostと登録する。

ただ、CLOUD9はサーバーを再起動するごとに、IPアドレスが変わってしまうので
下手にリファラーを登録すると、Google Maps APIにアクセスができなくなります。

スクリーンショット 2021-01-27 22.08.51.png

こんな感じで、設定していましたが

スクリーンショット 2021-01-27 21.58.18.png

制限なしに変更しました。

すると、登録した住所から緯度、経度を算出できるようになりました。
セキュリティ的には、設定したほうがいいんでしょうけどね
今回は、動いたので良しとしました笑

同じ様なエラーにハマっている方の手助けになればと思います。

参考記事

【Rails】Google Mapの表示方法
【Rails】Geocoding APIを用いて高精度で緯度経度を算出し、Google Mapに表示する方法
Rails 登録した住所をGoogle Mapで表示させる
Rails5でGoogleMapを表示してみるまで

9
10
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
9
10