【Rails6 / Google Map API】住所を投稿してマップに複数マーカーを立てる （モデルを介さないver.)

## つくるもの
こんな感じの投稿した住所または地名から緯度と経度を取得して各投稿の地点にマーカーを立てるマップです。
（「東京都墨田区押上１丁目１−２」（スカイツリー）のように住所を投稿することも可能です）
![スクリーンショット 2021-02-04 16.53.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/87929024-074e-f760-16ac-57800f854143.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テーブルを作りました。

![スクリーンショット 2021-02-04 15.49.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/2f0d5c7f-787f-1c73-fd23-fad8b3c15c6c.png)
こんな感じです！

#### 流れ
1. マーカーを立てるために、投稿された`address`から緯度・経度を取得するための記述をscriptタグ内に加える。
2. 取得した緯度・経度から投稿分のマーカーを立てる。

ざっとこれだけです！非常に簡単ですね！
それでは早速やっていきましょう！


# 実装

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

###1. 緯度・経度の取得
緯度・経度を取得するにはGeocodingを行います。
#### 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を使用することができます。

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

#### 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が取得してくれるようになる。


では、実際に実装しましょう！

```index.html.erb
<div id="map"></div>
<script>
    let map;
        function initMap() {
            map = new google.maps.Map(document.getElementById("map"), {
                center:{lat: 35.68123620000001, lng:139.7671248},
                zoom: 12,
            });
        }
</script>

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

```

もともとのscriptタグがこれ。
そこに以下の内容を付け加えることで各投稿から緯度・経度を取得することができます。

```index.html.erb
<div id="map"></div>
<script>
    let map;
        function initMap() {
            map = new google.maps.Map(document.getElementById("map"), {
                center:{lat: 35.68123620000001, lng:139.7671248},
                zoom: 12,
            });
            // ここから
            <% @maps.each do |m| %>
                <% results = Geocoder.search(m.address) %>
                <% if results.present? %>
                    <% @latlng = results.first.coordinates %>

                <% end %>
            <% end %>
            // ここまで
        }
</script>

```

これで各投稿の緯度・経度が`@latlng`に代入されました。
次はこの`@latlng`を使ってそれぞれの地点にマーカーを立てていこう！

###2.マーカーを立てよう！
1で緯度・経度の取得はできたのであとはその地点にマーカーを立てる記述をするだけです！
以下の記述を加えてください。

```index.html.erb
<div id="map"></div>
<script>
    let map;
        function initMap() {
            map = new google.maps.Map(document.getElementById("map"), {
                center:{lat: 35.68123620000001, lng:139.7671248},
                zoom: 12,
            });
            <% @maps.each do |m| %>
                <% results = Geocoder.search(m.address) %>
                <% if results.present? %>
                    <% @latlng = results.first.coordinates %>
                    // ここから
                    (function() {
                        let marker = new google.maps.Marker({
                            position:{lat: <%= @latlng[0] %>, lng: <%= @latlng[1] %>},
                            map: map
                        });
                    })();
                    // ここまで
                <% end %>
            <% end %>
        }
</script>

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

```

すると、、、
![スクリーンショット 2021-02-04 16.40.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/1f77428c-2163-b277-22ae-d9ef0e680141.png)

このようにマップにマーカーが立ちました。
以上。

（turbolinksを無効にしてあげないと特に詳細度の高い住所のマーカーは立たないかもです。）

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


# 参考記事
- [【Rails6 / Google Map API】初学者向け！Ruby on Railsで簡単にGoogle Map APIの導入する](https://qiita.com/nagaseToya/items/e49977efb686ed05eadb "マップ表示について")