【Rails6 / Google Map API】住所を投稿する際に予測変換させる（Autocomplete）

![map3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/d95c4f55-6068-4e65-76b3-04b66309a881.gif)
# はじめに
なにかサービスを作る上でユーザーのことを考えて作ることって大切ですよね！
マップを使ったサービスを作る時もそうです！投稿する際にいちいちユーザーに住所や地名を打たせるのは胸が痛くなります。笑
そこで今回は地名の予測変換機能を作ってみました！

# つくるもの
今回は以下のような投稿時の予測変換機能をつくっていきます！

![map.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/065222fb-dc93-ab2c-6a9d-e2d5bc0dc9b9.gif)

こんな感じです。

# 用意しておくもの
### 前提知識
今回はマップ表示とマーカーの設置はできてるものとして進めます！
なのでそこの部分に関しては、[こちら](https://qiita.com/nagaseToya/items/e49977efb686ed05eadb "railsでgooglemap")の記事をご覧ください。

必要なAPI
・Maps JavaScript API
・Geocoding API
### 機能
機能に関してはなにかしらの投稿フォームがあればOKです！！

# 実装
### 流れ
1. 用意した投稿フォームの下にマップを設置する。
2. 入力した住所や地名の場所にマーカーが立つようにする。
3. 住所や地名を入力する際に予測変換がでてくるようにする。

だいたいこのような流れです！
それではさっそく実装していきましょう！

##1. 用意した投稿フォームの下にマップを設置する!
![スクリーンショット 2021-02-05 15.20.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/f10dc241-0a3c-dda9-c426-53984a379bab.png)

これが用意してあるフォームです。
ここにマップを設置します！

![スクリーンショット 2021-02-05 15.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/6deb5582-1a4e-5757-9e9c-0941f888b3c0.png)

```new.html.erb
<%= form_with model:@map do |f| %>
    <div class="field">
        <div>
            <%= f.label :"住所または地名" %>
        </div>
        <%= f.text_field :address %>
        <div id="map"></div>
    </div>
    <%= f.submit %>
<% end %>
<script>
    let map
    function initMap() {
        map = new google.maps.Map(document.getElementById("map"), {
            center: {lat:34.965106 , lng:136.624412},
            zoom: 12
        });
    }
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLEMAPS_API_KEY']%>&callback=initMap"defer></script>
```

こんな感じですね！

##2. 入力した住所や地名の場所にマーカーが立つようにする

![map2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/95d3aaab-f8a3-a427-2edc-cffcdcdb0eb6.gif)


こんな感じに実装していきます！

```new.html.erb
<%= form_with model:@map do |f| %>
    <div class="field">
        <div>
            <%= f.label :"住所または地名" %>
        </div>
        <%= f.text_field :address,size: "40x20", id:"pac-input", onChange:"codeAddress()" %> // ここを変更
        <div id="map"></div>
    </div>
    <%= f.submit %>
<% end %>
<script>
    let geocoder　// ここも追加
    let map
    function initMap() {
        geocoder = new google.maps.Geocoder()
        map = new google.maps.Map(document.getElementById("map"), {
            center: {lat:34.965106 , lng:136.624412},
            zoom: 12
        });
    }
    // ここから
    function codeAddress(){
        let inputAddress = document.getElementById('pac-input').value;
        geocoder.geocode( { 'address': inputAddress}, function(results, status) {
            if (status == 'OK') {
                map.setCenter(results[0].geometry.location);
                let 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=<%= ENV['GOOGLEMAPS_API_KEY'] %>&callback=initMap"defer></script>
```

以上の変更箇所や追加箇所をもれなくいじるとGIF動画のようになると思います。

##3. 住所や地名を入力する際に予測変換がでてくるようにする
ここからがいそがしいです。:sweat:

詳しい住所込みの予測変換をするためには新たにAPIを追加する必要があります。
その名も「Places API」
詳しくはこちらの[公式ドキュメント](https://developers.google.com/places/web-service/overview?hl=ja)をご覧ください。

### Place APIを登録する

まずはこちらの[Google Cloud Platform](https://console.cloud.google.com/home/dashboard?project=mapapp-293715&hl=ja)に入ってください。
`左上のナビゲーションメニュー`→`APIとサービス`→`ライブラリ` へと進んでください。
そこに`Places API`があるのでクリックしてAPIを有効にしてください。

有効にした後に、`左上のナビゲーションメニュー`→`APIとサービス`→`認証情報`→`APIの制限`でPlaces APIも選択しておいてください。

これでPlaces APIの登録は完了です。
あとは、ひたすらコードと向き合うだけ！

```index.html.erb
<%= form_with model:@map do |f| %>
    <div class="field">
        <div>
            <%= f.label :"住所または地名" %>
        </div>
        <%= f.text_field :address,size: "40x20", id:"pac-input", onChange:"codeAddress()" %>
        <div id="map"></div>
    </div>
    <%= f.submit %>
<% end %>
<script>
    let geocoder
    let map
    function initMap() {
        geocoder = new google.maps.Geocoder()
        map = new google.maps.Map(document.getElementById("map"), {
            center: {lat:34.965106 , lng:136.624412},
            zoom: 12
        });
　　　　　// ここから
        const input = document.getElementById("pac-input");
        const autocomplete = new google.maps.places.Autocomplete(input);
        autocomplete.bindTo("bounds", map);
        // ここまで
    }
        function codeAddress(){
            let inputAddress = document.getElementById('pac-input').value;

            geocoder.geocode( { 'address': inputAddress}, function(results, status) {
                if (status == 'OK') {
                    map.setCenter(results[0].geometry.location);
                    let 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=<%= ENV['GOOGLEMAPS_API_KEY'] %>&callback=initMap&libraries=places&v=weekly"defer></script>
```

以上を追加してください！
すると完成です！！！

![map3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674324/fd29468d-88c7-b882-536a-c7158271ade8.gif)

どうでしたか？
うまいこと表示できましたか？？
私自身もまだ解読できていない部分がちょろっとあるのでお勉強しておきます。笑
では！

# 参考記事
・ [【Rails6 / Google Map API】初学者向け！Ruby on Railsで簡単にGoogle Map APIの導入する](https://qiita.com/nagaseToya/items/e49977efb686ed05eadb "railsでgooglemap")
・ [Places API 公式ドキュメント](https://developers.google.com/places/web-service/overview?hl=ja)