Railsで住所から緯度と経度を取得し、GoogleMapを表示しよう

#目標
<b>住所を入力すると、GoogleMapにピンが立つようにする</b>
#実装
<b>MAPモデル</b>

| カラム名| 型|内容|
|:--|:--|:--|
|address|string型|場所の名前や住所|
|latitude|float型|addressの緯度|
|longitude|float型|addressの経度|


#準備
GoogleMapのAPIを取得しよう
(参考:https://nendeb.com/276 )

#実装
##アプリケーションの作成
```
$ rails new address_sample
$ cd address_sample
```
Gemfileに以下を追加しよう

```Gemfile.
gem 'http'
```

Windowsの人はOpenSSLがデフォルトで入っていないので次のgemもGemfileに追加してください

```Gemfile.
gem 'openssl'
```

```
$ bundle install
$ rails g scaffold map address:string latitude:float longitude:float
$ rails db:migrate
```

##モデルの変更
after_validationによってバリデーションが行われた直後(テーブル内容に変更があった時)に `geocode` を実行できるようにします。
`geocode` の内容はGoogleのgeocodingするAPIを叩いて、返ってきた緯度と経度の情報をMapテーブルの `latitude`と　`longitude`に入れます。
uriのURL部分に先ほど取得したAPIキーを忘れずに入れてください。(参考:https://nendeb.com/276 )

```app/models/map.rb
class Map < ApplicationRecord
  after_validation :geocode

  private
  def geocode
    uri = URI.escape("https://maps.googleapis.com/maps/api/geocode/json?address="+self.address.gsub(" ", "")+"&key=[ここにAPIキー]")
    res = HTTP.get(uri).to_s
    response = JSON.parse(res)
    self.latitude = response["results"][0]["geometry"]["location"]["lat"]
    self.longitude = response["results"][0]["geometry"]["location"]["lng"]
  end
end
```

##ビューの変更
###入力項目を削除
緯度と経度は自動でレコードに追加されるようにするので、`views/maps/_form.html.erb` の緯度と経度を入力させる以下の部分を<b><font color=red>削除</font></b>しよう

```erb:app/views/maps/_form.html.erb
<div class="field">
  <%= form.label :latitude %>
  <%= form.text_field :latitude %>
</div>

<div class="field">
  <%= form.label :longitude %>
  <%= form.text_field :longitude %>
</div>
```

###javascriptでmapを表示させる

`maps/show.html.erb`の1行目に以下を追加してください。これがmapを表示させる場所です。

```html:app/views/maps/show.html.erb
<div id=map></div> 
```

さらに、同じ`maps/show.html.erb`の一番下に以下を追加してください。これがmapを表示させるjavascriptです。ここにもAPIキーを入力してください。(参考:https://nendeb.com/276 )
`var test`で緯度と経度を受け取り、それをGoogleMapに渡すことでGoogleMapに表示できるようになります。


```html:app/views/maps/show.html.erb
<script type="text/javascript">
  function initMap() {

    var test = {lat: <%= @map.latitude %>, lng: <%= @map.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 = '住所：<%= @map.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>

```


###cssでmapの大きさを指定する
application.cssに以下を追加します。これにより、mapの大きさを指定することができます。

```app/assets/stylesheets/application.css
#map {
  height: 400px;
  margin-left:auto;
  margin-right:auto;
  text-align:left;
  width: 80%
}

```

##投稿してみよう
`localhost:3000/maps/new`から住所や場所を投稿してみよう。投稿するとshowのページに飛んでGoogleMapが表示されてるはずです
<img width="1331" alt="スクリーンショット 2018-10-09 14.18.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/225909/4260df95-bdb2-db03-0bab-2adb1d8fd1d6.png">