【Ruby on Rails】Googlemapの複数ピン立て、吹き出し、リンク

# 目標
![map複数.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700999/b60cc4f1-94fb-e731-cc7e-15b196beb8a2.gif)


# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

# 前提
※　▶◯◯　を選択すると、説明等が出てきますので、
　　よくわからない場合の参考にしていただければと思います。

- [【Ruby on Rails】郵便番号から住所を自動入力](https://qiita.com/japwork/items/8667a076777fab35c0c4)
- GoogleAPIキー発行済(GeocodingAPI MapsJavaScriptAPI)　
 - こちらで分かりやすく説明してくれていました
 - [Rails5でGoogleMapを表示してみるまで](https://qiita.com/tiara/items/4a1c98418917a0e74cbb)
- [【Ruby on Rails】Google API を使ったGoolgeMAPの表示とピン立て](https://qiita.com/japwork/items/ef3ba0fec2a61bb3874a)

既に1件は表示はできている前提で進めていきます。



# 1 gemの導入
下記をGemfileに追加。

```:Gemfile
gem "gon"
```
```:ターミナル
$ bundle install
```
<details><summary>補足</summary>
gonはcontroller内の変数をJavascript内で使う事が出来るgemです。</details>


# 2 controllerの編集
gon.users を定義する。

```rb:app/controllers/users_controller.erb
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  end

  def index
    @users = User.all
    gon.users = User.all
  end
end
``` 

# 3 viewの編集
<%= include_gon %>を記述することで、Javascript内で使用可能にする。

```erb:app/views/layouts/application.html.erb
<head>
...
  <%= include_gon %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
...
<head>
```
今回は下記ページに記載。

```erb:app/views/users/index.html.erb
<div id='map'></div>
<style>
#map{
    height: 500px;
    width: 530px;
}
</style>

<script>

let map
let geocoder
let marker = []; // マーカーを複数表示させたいので、配列化
let infoWindow = []; // 吹き出しを複数表示させたいので、配列化
const users = gon.users; // コントローラーで定義したインスタンス変数を変数に代入


function initMap(){
    // geocoderを初期化
    geocoder = new google.maps.Geocoder()
    // mapの初期位置設定
    map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: -35.6809591, lng: 139.7673068},
    zoom: 14
    });
    // forは繰り返し処理
    // 変数iを0と定義し、
    // その後gonで定義したusers分繰り返し加える処理を行う
    for (let i = 0; i < users.length; i++) {
        // geocoderで addressの経緯緯度取得
        // users[i]は変数iのユーザーを取得している
        geocoder.geocode( { 'address': users[i].prefecture_code + users[i].city + users[i].street }, function(results, status) {
            // statusがOKであれば
        if (status == 'OK') {
    　　　　// map.setCenterで地図が移動
            map.setCenter(results[0].geometry.location);
            marker[i] = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
            // 変数iを変数idに代入
            let id = users[i]['id']
            // infoWindowは吹き出し
            infoWindow[i] = new google.maps.InfoWindow({
            // contentで中身を指定
            // 今回は文字にリンクを貼り付けた形で表示
            content: `<a href='/users/${id}'>${users[i].email}</a>`
            });
            // markerがクリックされた時、
            marker[i].addListener("click", function(){
                // infoWindowを表示
                infoWindow[i].open(map, marker[i]);
            });
        } else {
            alert('Geocode was not successful for the following reason: ' + status);
        }
        });
    }
}

function codeAddress(){
    // 入力を取得
    let inputAddress = document.getElementById('address').value;
    // geocodingしたあとmapを移動
}
</script>

<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['SECRET_KEY'] %>&callback=initMap" async defer></script>
```
<details><summary>補足【うまくいかない時】</summary>
住所の登録ができているものの、ピン立てされていない時、
[Geocoding Service](https://developers.google.com/maps/documentation/javascript/geocoding)
これを参考にGeocoding APIを有効化すればOK。</details>