【Rails6 / Google Map API】初学者向け！Ruby on Railsで簡単にGoogle Map APIの導入する

#はじめに

##つくるもの
Google Map APIを導入しページに地図を表示させます。
今回は検索した住所にピンを立て、そこの緯度経度を表示させるまでを実装します。

![gmap-step0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/64efd05c-c327-01cf-54d5-02132af2e4a3.gif)


#コードを書く前に
Google Maps API を利用するには、API キーという許可証のようなものを取得する必要があります。
API キーを取得する為にGoogle アカウントが必要になるため、事前に準備しておきましょう。

[Google アカウントの作成はこちらから](https://accounts.google.com/signup/v2/webcreateaccount?hl=ja&flowName=GlifWebSignIn&flowEntry=SignUp)

そして[Google Cloud Platform](https://console.cloud.google.com/?hl=ja
)へアクセスして、APIキーを取得しましょう。

##プロジェクトの作成
![gmap-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/e6335ef6-9d60-ca9d-524f-73964fa20e82.png)

![gmap-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/af8c4d32-9579-c0cf-76a1-d64bb98fe12e.png)

![gamp-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/3ba9ab56-079d-904c-2648-7865804b011b.png)

![gmap-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/2cc3a29e-58cf-defa-49d7-0486c898aae3.png)


##APIの有効化
![gmap-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/d175eaf2-55a0-9864-7c00-f9c9623af7eb.png)

![gamp-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/4037506f-3a41-8b71-2757-ea39ed56326e.png)

##APIキーの作成
![gmap-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/ccb32f89-0ca4-0869-2b95-dbd284cbc696.png)

![gmap-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/52da316a-c409-eb44-d8e1-0ca7deeb455a.png)

![gmap-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/64eb6ea4-f829-51e1-140f-1418991500c6.png)

![gmap-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/ec69a6ba-f3fb-cc4e-2c4b-6eceec267d0d.png)

![gmap-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/c330eaf1-38ea-4305-ac65-431260644fff.png)

![gmap-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/333ceab6-4811-c689-875f-5eff0b7fb3fe.png)

![gmap-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/72033149-d81a-588e-4d69-78de356f7801.png)


![gmap-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/a67495ca-9415-88d5-fad2-c0ee808bb7a2.png)

![gmap-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/3fc943c5-27cf-d1d5-00e2-e294e69ca77c.png)

![gmap-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/5593e295-0e72-10bb-2eb4-e93baa1a158c.png)


##移行ツール
課金設定をしていないと、いざ地図を表示しようとしてもエラーが出てしまいます。
エラー文は以下の通りです。
`You have exceeded your request quota for this API. 
See https://developers.google.com/maps/documentation/javascript/error-messages?utm_source=maps_js&utm_medium=degraded&utm_campaign=billing#api-key-and-billing-errors`

[移行ツール](https://mapsplatformtransition.withgoogle.com/auth_required) にアクセスし、手順にしたがって登録します。

#アプリケーション作成
長きにわたる諸々の設定おつかれさまでした。
ここから早速アプリケーションを作っていきましょう。

ファイルを作成する前に先ほど作成したAPIキーを用意しておいてください。

##登場人物
今回作成・編集するページは

- routes.rb
- maps_controller.rb
- index.html.erb

この3つです。それぞれのファイルに書き込んでください。

###ルーティング

```rb:routes.rb

Rails.application.routes.draw do
  get 'maps/index'
  root to: 'maps#index'
  resources :maps, only: [:index]
end
```

###コントローラー

```rb:maps_controller.rb

class MapsController < ApplicationController
  def index
  end
end
```

###ビューページ

![マップ完成イメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/e0babae9-c780-1798-9b86-e7d037f99baf.png)


##ビュー作成
###地図を表示させる
では以下のコードをファイルにコピーしてみましょう。

```erb:index.html.erb

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

<style>
#map {
  height: 600px;
  width: 600px;
}
</style>

<script>
let map

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

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

  marker = new google.maps.Marker({
    position:  {lat: 40.7828, lng:-73.9653},
    map: map
  });
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
```

`<style>`タグでマップの大きさを指定していますが、ここを省いてしまうと地図が表示されないので必ず書きましょう。

```css
<style>#map {height: 600px;width: 600px;}</style>
```

次に地図の初期設定についてですが、 `center`で初期位置の緯度経度を指定し、 `zoom`で表示領域の大きさを決めます。

```js

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

  map = new google.maps.Map(document.getElementById('map'), {
    //latが緯度、lngが経度を示します
    center: {lat: 40.7828, lng:-73.9653},
    //数値は0〜21まで指定できます。数値が大きいほど拡大されます
    zoom: 12,
  });
  //positionに指定した座標にピンを表示させます
  marker = new google.maps.Marker({
    position:  {lat: 40.7828, lng:-73.9653},
    map: map
  });
}
```

そして最後の行の `YOUR_API_KEY`の部分に自分で作成したキーを入れてください。

```erb

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

ではここで実際にブラウザで地図が表示されるか確認してみましょう。
以下のように表示されたでしょうか？

![gmap-step1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/1e71db3e-4303-bfcb-9a2c-f72ee94aa6cd.png)

###検索フォームから住所を特定しピンを刺す
次に検索フォームを作成します。

```erb:index.html.erb

<h2>gmap</h2>

<!-- ここから追加 -->
<input id="address" type="textbox" value="GeekSalon">
<input type="button" value="Encode" onclick="codeAddress()">
<!-- ここまで追加-->

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

<style>
#map {
  height: 600px;
  width: 600px;
}
</style>

<script>
let map
function initMap(){
  geocoder = new google.maps.Geocoder()

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

  marker = new google.maps.Marker({
    position:  {lat: 40.7828, lng:-73.9653},
    map: map
  });
}
// ここから追加 
let geocoder

function codeAddress(){
  let inputAddress = document.getElementById('address').value;

  geocoder.geocode( { 'address': inputAddress}, function(results, status) {
    if (status == 'OK') {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
          map: map,
          position: results[0].geometry.location
      });
    } else {
      alert('該当する結果がありませんでした：' + status);
    }
  });   
}
// ここまで追加 
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
```
２箇所追加しました。
ビューに関する部分では検索フォームとボタンを作成しました。

```erb

<input id="address" type="textbox" value="GeekSalon">
<input type="button" value="Encode" onclick="codeAddress()">
```
次に `<script>`タグ内に検索機能の処理を追加しました。

```js

let geocoder

  //検索フォームのボタンが押された時に実行される
function codeAddress(){
  //検索フォームの入力内容を取得
  let inputAddress = document.getElementById('address').value;

  geocoder.geocode( { 'address': inputAddress}, function(results, status) {
    //該当する検索結果がヒットした時に、地図の中心を検索結果の緯度経度に更新する
    if (status == 'OK') {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
          map: map,
          position: results[0].geometry.location
      });
    } else {
      //検索結果が何もなかった場合に表示
      alert('該当する結果がありませんでした：' + status);
    }
  });   
}
```

では早速ブラウザを開いて見てみましょう。
以下のように検索結果に応じて結果が処理される機能をつけました。

![gmap-step2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/08b1e3be-7ca1-bc22-3066-a06ab66158f1.gif)


###検索結果から緯度経度を取得し、表示させる
さて初めてのGoogleマップ講座もいよいよ大詰めです。
最後に検索結果の緯度経度をページに表示させましょう。

コードは以下の通りです。

```erb:index.html.erb

<h2>gmap</h2>

<input id="address" type="textbox" value="GeekSalon">
<input type="button" value="Encode" onclick="codeAddress()">
<!-- 下の1行を追加 -->
<div id="display">何かが表示される、、、、！</div>

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

<style>
#map {
  height: 600px;
  width: 600px;
}
</style>

<script>
let map
let geocoder
// 下の1行を追加 
const display = document.getElementById('display')

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

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

  marker = new google.maps.Marker({
    position:  {lat: 40.7828, lng:-73.9653},
    map: map
  });
}

function codeAddress(){
  let inputAddress = document.getElementById('address').value;

  geocoder.geocode( { 'address': inputAddress}, function(results, status) {
    if (status == 'OK') {
      map.setCenter(results[0].geometry.location);
      var marker = new google.maps.Marker({
          map: map,
          position: results[0].geometry.location
      });
      // 下の1行を追加 
      display.textContent = "検索結果：" + results[ 0 ].geometry.location
    } else {
      alert('該当する結果がありませんでした：' + status);
    }
  });   
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
```
ビューに関して１箇所、 `<script>`タグ内に２箇所追加しました。
それぞれ追加する場所を確認し、追加して見てください。
追加した要素・処理は

- 検索結果を表示させるためのディスプレイ
- ディスプレイの情報を取得
- 検索結果をディスプレイに表示

の3つです。なので追加箇所も３箇所です。
これでコードの書き込みは完了です。

ではでは最後にブラウザを開いて確認してみましょう。
検索結果がディスプレイに表示されれば完成です。

![gmap-step3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452149/bf5787f0-9867-de4c-fc4c-32c66153bcd4.gif)

#復習
ファイルの中身を編集して、地図の初期位置を自分のお気に入りスポットに変えてみましょう！