Waku×2 プログラミング生活

駆け出しエンジニアが楽しみながら成長していくブログ

Rails5でGoogleMapを表示させる

Rails5でGoogleMapを表示させる

 なんだかんだでブログを作ったはいいが、投稿できていなかったので、初投稿。

 

 現在プログラミングのスクールに通いながら作っている飲食店のレビューを管理するアプリケーション(食べログのクローンサイト)で、お店の詳細画面に地図を表示させたくて、GoogleMapを使って表示したくて試行錯誤した結果、数日かかったけれどとりあえず動くようになったのでメモとして書いておきます(とりあえず公開してあとで編集します!)。

 

 

やりたかったこと

  • お店の新規登録の際に入力した住所からお店の座標(緯度と経度)を割り出して、GoogleMapで表示させる。
  • 表示したお店の座標を登録して、お店のページでGoogleMapでお店の場所を表示させる。

やったこと

  • gemの導入(gmaps4rails, geocoder)
  • DBのテーブルにlatitudeとlongitudeカラムを追加する
  • application.html.hamlのhead部分にjQueryとGoogleAPIのscriptを読み込む記述を行う
  • underscore.jsをコピペ(Gmaps4railsが使うやつ)
  • jsファイルgooglemap.jsを編集
  • viewの編集
1. GoogleAPIキーの取得

Google Mapを使用するためにはGoogle APIを取得する必要があります。

以下のリンクや、「Google API 取得」等で検索して出てきたサイトを参考に取得しました。

https://developers.google.com/maps/documentation/javascript/get-api-key

取得したら、Maps JavaScript APIとGeocoding APIを有効化します。

 

2. gem の導入

Gemfileを編集します。

gem 'geocoder'
gem 'gmaps4rails'



3. データベースのテーブルにlatitudeとlongitudeカラムを追加する

 開発していたアプリケーションでは、店舗の情報を管理しているテーブルshopsテーブルに新しく店舗の座標を登録するため、latitudeカラムとlongitudeカラムを追加しました。

ターミナル

$ rails g migration AddMapInfoToShops 

Migration File ( db/migrate/xxxxxxxx_add_map_info_to_shops.rb )

class AddMapInfoToShops < ActiveRecord::Migration[5.0]
  def change
    add_column :shops, :latitude, :float
    add_column :shops, :longitude, :float
  end
end

 


4. application.html.hamlのhead部分にjQueryとGoogleAPIのscriptを読み込む記述を行う

1で取得して有効化したAPIキーを下記コードのYOUR_API_KEY部分に記述する。

app/views/layouts/application.html.haml

%script{:async => "", :defer => "defer", :src => "https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"}
%script{:src => "//cdn.rawgit.com/mahnunchik/markerclustererplus/master/dist/markerclusterer.min.js"}
5. underscore.jsをコピペ(Gmaps4railsが使うやつ)

underscore.jsのリンク
上のリンク先のコードをコピーして、underscore.js ファイルを作って中に貼り付けます。
app/assets/javascripts/underscore.js 

// underscore-min.jsの中身をコピペ。
6. jsファイルgooglemap.jsを編集
// 店舗新規登録画面
// Mapの表示
//マップオブジェクト
var gMap = null;
//マーカーオブジェクト
var gMarkerCenter = null;

function initMap(){
 // 緯度経度から地図を表示
  var lat = $('#shop_latitude').val();
  var lng = $('#shop_longitude').val();
// 座標を設定
  var myLatLng = new google.maps.LatLng(lat, lng)
  var mapOptions = {
    center: myLatLng,
    zoom: 15,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
// マップオブジェクトの生成、マーカー生成
  gMap = new google.maps.Map(document.getElementById("map"), mapOptions);
  gMarkerCenter = drawMarkerCenterInit(myLatLng);
}
// マーカー生成関数
function drawMarkerCenterInit(pos) {
  var markerCenter = new google.maps.Marker({
    position: pos,
    map: gMap,
    draggable: true
 });
  return markerCenter;
}

$(function(){
  // 検索ボタンをクリックした時
  $('#searchAddressBtn').click(function() {
    // Geocoderオブジェクト生成
    var geocoder = new google.maps.Geocoder();
    // 住所のテキストボックスから住所取得
    var address = $('.city_address').val();
    // 住所検索実行
    geocoder.geocode(
      {
        'address' : address,
        'region' : 'jp'
      },
      function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          // 住所のデータを取得できた時
          // 取得した座標をマップに反映
          gMap.setCenter(results[0].geometry.location);
          // 取得した座標をマーカーに反映
          var pos = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
          gMarkerCenter.setPosition(pos);

          // 取得した座標をテキストボックスにセット
          $('#shop_latitude').val(pos.lat());
          $('#shop_longitude').val(pos.lng());

          } else {
            // 失敗した時
              alert('住所検索に失敗しました。<br>住所が正しいか確認してください');
          }
      });
  });
});

// 店舗ページで地図を表示
$(function(){
  handler = Gmaps.build('Google');
  handler.buildMap({ provider: { scrollwheel: false }, internal: {id: 'map1'}}, function(){
    markers = handler.addMarkers([
      {
        "lat": gon.shop.latitude,
        "lng": gon.shop.longitude,
    "infowindow": '<p>'+ gon.shop.shop_name +'</p><p>'+ gon.shop.city_address +'</p><p> link_to "Googleマップで見る" ,"https://maps.google.co.jp/maps?q=loc:'+ gon.shop.latitude +','+ gon.shop.longitude +'&iwloc=J",target: "_blank"</p>'
      }
    ]);
    handler.bounds.extendWith(markers);
    handler.fitMapToBounds();
    handler.getMap().setZoom(16);
  });
});


7. viewの編集

お店の新規登録画面で、city_addressの入力フィールドに入力された住所を元に、
geocoderが座標を取得、すぐさま入力フィールド下にGoogleMapで表示させます。

app/views/shops/new.html.haml

//form_forを使って店舗の情報を保存する
= form_for @shop do |f|

//省略

//入力フィールド
  = f.text_field :city_address, class:"city_address"
    %button{id:"searchAddressBtn", value:"検索", type:"button"}
      場所を検索

//省略

//地図の描画
  #map{:style => "width: 100%; height: 160px;"}
            = f.text_field :latitude, readonly:"readonly"    //緯度の表示
            = f.text_field :longitude, readonly:"readonly" //経度の表示

//省略

//上記緯度と経度を店舗の情報と一緒にテーブルに保存する
  = f.submit "登録する", class: "submit_btn"


下記の様に、市町村区・番地の入力フィールドに住所を入力した後、検索ボタンを押すと、
その下のGoogleMap上に描画されます。
f:id:ywatanab0301:20181019110426p:plain


お店の情報ページでは、上記でお店の情報テーブルに保存された緯度と経度を取得することで、
GoogleMapを描画します。

app/views/shops/show_map.html.haml

#map{:style => "width: 100%; height: 600px;"}


こんな感じで表示されます。
f:id:ywatanab0301:20181019113318p:plain


GoogleのGeocoding APIは、その画面で即GoogleMapを表示させないといけないようです。