【Rails6 / Google Map API】住所を投稿してマップに複数マーカーを立てる


# はじめに

## つくるもの
こんな感じの投稿した住所または地名から緯度と経度を所得してそれぞれの地点にマーカーを立てるマップです。
（「東京都墨田区押上１丁目１−２」（スカイツリー）のように住所を投稿することも可能です）
![スクリーンショット 2020-08-28 1.54.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/d1774490-5d6d-1282-e7bd-30aa88610b0c.png)

## 用意しておくもの
#### 前提知識
今回はGoogleMapAPIを用いたマップの表示はできているものとして進めていきます。

必要なAPI
・Maps JavaScript API
・Geocoding API

GoogleMapAPIを用いたマップの表示がわからない人は下記の記事をお読みください。
上記APIの導入方法とマップの表示方法が書いてあります。
[【Rails6 / Google Map API】初学者向け！Ruby on Railsで簡単にGoogle Map APIの導入する](https://qiita.com/nagaseToya/items/e49977efb686ed05eadb "マップ表示について")

#### 機能
シンプルな投稿機能は用意しておいてください。
筆者は住所や地名を投稿するためのaddressカラムを持った、mapsテーブルを作りました。
![スクリーンショット 2020-08-29 16.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/05a29f94-020a-bcd8-5639-23341d3e380e.png)
こんな感じです！

#### 流れ
1. 緯度・経度を保存するためのlatitudeカラムとlongitudeカラムをmapsテーブルに追加する。
2. Geocoderを利用して、入力された住所または地名から緯度・経度を取得しそれぞれをlatitudeカラムとlongitudeカラムに保存できるようにする。
3. 投稿された緯度・経度の地点にマーカーを立てる。


# 実装

上記の流れに沿って実装していきます！

###1. カラム追加

```
$ rails g migration AddCoordinateToMaps latitude:float longitude:float
```
上記コマンドで`latitude`と`longitude`の２つのカラムを追加するためのマイグレーションファイルを作成します。

```
$ rails db:migrate
```
忘れずにマイグレートしましょう！

###2. Geocoderを利用して緯度・経度を取得する
#### Geocoding
- Q. そもそもGeocodingとは？？
- A. 住所や地名から座標（緯度・経度）を取得したり、座標から住所や地名を取得すること。
またIPアドレスからも住所や地名を取得することもできる。

ちなみに下記の記事はGeocodingに関して詳しく書いてくれているのでもっと詳しく知りたい人は是非ご覧ください。
[RailsのGeocoderとあそぼ](https://qiita.com/tiara/items/573fe5f1a84ca57dabcd "Geocoderとあそぼ")

#### 必要なgemをインストール

```gemfile
gem 'geocoder'
```

上記のコードをgemファイルの中に記述する。

```
$ bundle install
```

しっかりと`bundle install`を行いましょう〜！
これでrailsの中でgeocoderを使用することができます。

#### モデルに対するGeocoding

```ruby:map.rb
class Map < ApplicationRecord
    geocoded_by :address
    after_validation :geocode
end
```

`:address`の部分にはGeocodingを行いたいカラムを書きます。
この2行を`address`、`latitude`、`longitude`を持ったモデルに対して記述してあげると、`address`に入力された住所や地名から緯度・経度を取得しそれぞれのカラムに保存してくれます。

そして一覧画面で`latitude`と`longitude`を表示してあげると以下のように緯度と経度がそれぞれ表示されるようになったと思います。

![スクリーンショット 2020-08-29 18.15.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/67b8807e-3483-2300-ff97-550558d1f218.png)

しかし、このままでは「東京都墨田区押上１丁目１−２」のように住所を投稿すると緯度と経度は取得できません。

#### geocoder用のコンフィグファイルを作成

以下のコマンドでコンフィグファイルを作成。

```
$ rails g geocoder:config
```

config/initializers/geocoder.rbというコンフィグファイルが生成されるので、そのファイルにgooglemapのAPI情報を記載します。

```ruby:config.initializers.geocoder.rb
Geocoder.configure(
  # Geocoding options
  timeout: 5,                 # geocoding service timeout (secs)
  lookup: :google,         # name of geocoding service (symbol)
  api_key: 'YOUR_API_KEY',               # API key for geocoding service
  units: :km,                 # :km for kilometers or :mi for miles
)
```

生成された`geocoder.rb`の中の`timeout`、`lookup`、`api_key`、`units`の４つの項目のコメントアウトを外し、必要事項を上記コードのように記入する。

こうすることで詳細度の高い住所もgeocoderが取得してくれるようになる。

###3. 投稿された位置にマーカーを表示する

```index.html.erb


<div id='map'></div>

<script>
  let map

    function initMap(){
      geocoder = new google.maps.Geocoder()

      map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: 35.68123620000001, lng:139.7671248},
          zoom: 12,
      });


      <% @maps.each do |m| %>
          (function(){
          var contentString = "住所：<%= m.address %>"; 

          var marker = new google.maps.Marker({
              position:{lat: <%= m.latitude %>, lng: <%= m.longitude %>},
              map: map,
              title: contentString
          });

          })();
      <% end %>
      }
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
```

上記コードのように`<% @maps.each do |m| %>` ~ `<% end %>`の中に繰り返し処理を行いたいコードを書くと投稿した住所や地名の位置にマーカーが立つようになります。
※住所をcontentStringに代入していますが、このように複数回使いそうな情報は変数に代入しておくと便利です。（吹き出しなどを追加で実装する際に使うことがあります。）
![スクリーンショット 2020-09-12 15.24.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/f227fee2-5659-ccb4-6f9c-1691680ddba5.png)


デプロイするときはちゃんとAPIキーは.envファイルに記入しgitignoreファイルに隠すようにしましょうね！
じゃないとあなたのAPIキーは全世界の人に丸見えになっちゃいますよ！
自分の身は自分で守ろう:thumbsup:

# 参考記事
- [RailsのGeocoderとあそぼ](https://qiita.com/tiara/items/573fe5f1a84ca57dabcd "Geocoderとあそぼ")
- [【Rails6 / Google Map API】初学者向け！Ruby on Railsで簡単にGoogle Map APIの導入する](https://qiita.com/nagaseToya/items/e49977efb686ed05eadb "マップ表示について")
- [Rails5でGoogleMapsAPIを用い、複数のマーカーを表示する](https://qiita.com/yamaotoko4177/items/30b72766d013904452fa
86ed05eadb "マップ表示について")
- [Ruby on RailsとGoogle Geocoding APIで住所から緯度・経度を取得する方法](https://programming-beginner-zeroichi.jp/articles/271
86ed05eadb "マップ表示について")