【Rails】住所を入力すると自動で地図表示される方法(Google Maps API)

#はじめに
ポートフォリオ制作で、Google Maps APIを用いて住所フォームを送信した際に住所名と地図を自動で地図表示される設定を行ったので、アウトプットも兼ねて手順を紹介していきます。


#手順
1.Google MapのAPI Keyを取得
2.住所(address)、緯度(latitude)、経度(longitude)カラムを追加する
3.住所を登録するフォームを作成する
4.gem geocoderを追加する
5.viewにGoogle Mapを表示させる記述を追加する
6.詳しい住所を表示させる
7.GitHubにPushされないように設定する
8.APIキーの書き換え
(その他)AWSでデプロイしている場合


#1.Google MapのAPI Keyを取得
APIの取得はこちらの記事がわかりやすいので参考にしてみてください。

https://qiita.com/tiara/items/4a1c98418917a0e74cbb

#2.住所、緯度、経度カラムを追加する

住所(address)、緯度(latitude)、経度(longitude)カラムを追加しましょう。


```
class ChangeDatatypeLanguageOfLabs < ActiveRecord::Migration[5.2]

  def change
        change_column :labs, :address, :string
        change_column :labs, :latitude, :float
        change_column :labs, :longitude, :float
  end
end
```

labsはモデル名なので人によって変わります。

latitudeとlongitudeは`float型`にします。

float型については下記の記事を参考にしてみてください。
https://wa3.i-3-i.info/word14968.html

カラムを追加したら`$ rails:db:migrate`を実行します。

#3.住所を登録するフォームを作成する

```
<%= form_for(@lab) do |f| %>
・・・
<%= f.label :住所 %>
<%= f.text_area :address, autofocus: true %>
・・・
<%= f.submit '投稿' %>
<% end %>
```
これで住所を登録するフォームが投稿できます。

#4.gem geocoderを追加する

地図表示する際に、Google Mapでは緯度・経度から位置を取得します。

なので、緯度・経度の登録を行う為に今回は`gem geocoder`を導入します。
`geocoder`によって住所の情報を元に緯度、経度を割り出してくれます。

```Gemfile.
gem 'geocoder'
```

記述後、ターミナル上で`$ bundle install`を実行します。


```lab.rb
  geocoded_by :address(←住所のカラム名)
  after_validation :geocode, if: :address_changed?
```

これで、モデル登録時と住所(address)変更時にgeocoderが動いて緯度・経度のデータが登録・更新されます 

#5.viewにGoogle Mapを表示させる記述を追加する
```labs/show.html.rb

・・・
<p>住所</p>
<p><%= @lab.address %></p>(住所名表示)

<div id="map"></div>(地図を表示)
・・・

<style>(地図の大きさ指定)
#map{
  height: 150px;
  width:270px;
}
</style>

<script type="text/javascript">
    function initMap() {

        var test ={lat: <%= @lab.latitude %>, lng: <%= @lab.longitude %>};
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 15,
            center: test
        });
        var transitLayer = new google.maps.TransitLayer();
        transitLayer.setMap(map);

        var contentString = '住所：<%= @lab.address %>';
        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position:test,
            map: map,
            title: contentString
        });

        marker.addListener('click', function() {
            infowindow.open(map, marker);
        });
    }
</script>

<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=取得したAPIキー&callback=initMap">
</script>
```

![map-google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607423/8f7ada00-18f6-4289-83c0-cd4ab30f77e9.png)


これで登録した住所を元に地図表示ができるようになりました。
しかし、この状態では住所名によって地図が表示されない場合があります。

それはデフォルトのgeocoderのままでは詳しい住所の経度、緯度を持ってくることができないからです。

なので、詳しい住所でも表示されるように設定していきます。

#6.詳しい住所を表示させる

ターミナル上で`$ bin/rails g geocoder:config`コマンドを入力。
そうすると、`config/initializers/geocoder.rb`ファイルが作成されます。


作成されたファイルを開き、中身を変更させましょう。

```geocoder.rb
Geocoder.configure(
  # Geocoding options
  # timeout: 3,                 # geocoding service timeout (secs)
   lookup: :google,         # name of geocoding service (symbol)
  # ip_lookup: :ipinfo_io,      # name of IP address geocoding service (symbol)
  # language: :en,              # ISO-639 language code
   use_https: true,           # use HTTPS for lookup requests? (if supported)
  # http_proxy: nil,            # HTTP proxy server (user:pass@host:port)
  # https_proxy: nil,           # HTTPS proxy server (user:pass@host:port)
   api_key: ENV['GOOGLE_MAP_API_KEY'],               # API key for geocoding service
  # cache: nil,                 # cache object (must respond to #[], #[]=, and #del)
  # cache_prefix: 'geocoder:',  # prefix (string) to use for all cache keys

  # Exceptions that should not be rescued by default
  # (if you want to implement custom error handling);
  # supports SocketError and Timeout::Error
  # always_raise: [],

  # Calculation options
  # units: :mi,                 # :km for kilometers or :mi for miles
  # distances: :linear          # :spherical or :linear
)
```
これで、Google mapのAPIを使って緯度、経度を検索できるようになりました。

#7.GitHubにPushされないように設定する

この状態でPushしてしまうと取得したAPIキーもGitHub上に上がってしまいます。
なので、Pushしても表示されないように設定しましょう。


gemの`dotev-rails`を用いて設定していきます。

```Gemfile.

gem 'dotenv-rails'
```
ターミナル上で`$ bundle install`を実行します。

app等と同じステージに.envファイルを作成しましょう。

![change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607423/2f1a3317-dda7-7843-8522-b532b618e98b.png)


`.env`ファイルにAPIキーを記述する。

```env.
GOOGLE_MAP_API_KEY=取得したAPIキー
```


`.env`ファイルの下にある
`.gitignore`ファイルの最後の行に.envと記述しましょう。
(ちなみにignoreとは無視するという意味です。)

```gitignore.
・・・
・・・
/.env
```

これでPushしても.envファイルは無視されます。

#8.APIキーの書き換え

今までAPIキーを直接書き込んでいた全てのファイルでAPIキーの記述を.envファイル内で定義したGOOGLE_MAP_API_KEYに書き換えます。


```labs/show.html.rb
<script async defer
        src="https://maps.googleapis.com/maps/api/js?v=3.exp&key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap">
</script>
```

```geocoder.rb
 api_key: ENV['GOOGLE_MAP_API_KEY'],  
```

これでGitHub上にAPIキーが上がることなく地図が表示されるようになります。

#(その他)AWSでデプロイしている場合

AWSでデプロイしている場合、本番環境に反映させる為には
EC２にログイン後、Git pullをして変更内容を取り込みます。

その後、`$ sudo vi .env`コマンドで.envファイルを開き、

```
GOOGLE_MAP_API_KEY=取得したAPIキー
```
を記述するとデプロイ先でも反映されるようになります。