はじめに
この記事では, RailsアプリでGoogle Mapを利用する方法を書き記しています.
特徴は以下です.
- Google MapのAPIを利用します
- APIキーは公開防止のため, .envファイルで管理します.
- Mapの緯度経度情報をデータベースに登録することで, 場所の投稿サイトを作ることができます.
- 投稿された内容はMap上にピンを立てるようにします.
- 場所を投稿すると, 自動で緯度経度を取得し, データベースに登録するようにします.
- ピンの情報ウィンドウをクリックすると投稿の詳細ページへ飛びます
うまく動作しないときは, ディベロッパーツールのコンソールにエラー文が出力されるため参考にしましょう.
もくじ
- Google Map APIを利用可能にする
- MVCを用意する & その他設定
- herokuにAPIを登録する
1. Google Map APIを利用可能にする
Google MapはもちろんGoogleが発表しているサービスです. このようなサービスはAPIと呼ばれる仕組みを通して他と連携して利用することができるようになります. 具体的には, APIキーを登録します. 以下のページにて作業します.
※前提としてgoogleアカウントが必要です. また, 形式上Googleアカウントにクレジットカードを登録している必要があります.
プロジェクトの作成
以下の手順に従ってプロジェクトを作成します.
APIキーの作成
以下の手順に従ってAPIキーを作成します.
作成されたAPIキーは後で利用するのでどこかにメモしておきましょう!
請求先アカウント設定
Google Map APIを利用するには, 形式上請求先アカウントを設定する必要があります. 請求情報を紐づけるだけで, 無課金設定のまま利用できます.
「お支払い」から請求先アカウントを作成します. このとき, Googleアカウントにクレジットカードを登録している必要があります.
画面の指示に従って登録しましょう.
2. MVCを用意する & その他設定
上記でGoogle Map APIを利用するための準備が整いました. 今度は, 自分のRailsアプリの設定をしていきます.
この記事では, 一例として以下のようにmapsテーブルを作成します.
また, indexページにて, 場所の表示と場所の投稿を両方できるようにします.
maps テーブル
address | latitude | longitude |
---|---|---|
東京駅 | 35.6812 | 139.7671 |
... | ... | ... |
mapsテーブル
以下のコマンドにより, address(住所), latitude(緯度), longitude(経度)を保存できるmapsテーブルを作成します.
$ rails g model Map address:string latitude:float longitude:float
$ rails db:migrate
mapsコントローラー
mapsコントローラー作成コマンド
$ rails g controller maps
コントローラーの記述は以下のようにします.
class MapsController < ApplicationController
def index
@maps = Map.all
@map = Map.new
end
def create
map = Map.new(map_params)
if map.save
redirect_to :action => "index"
else
redirect_to :action => "index"
end
end
def destroy
map = Map.find(params[:id])
map.destroy
redirect_to action: :index
end
private
def map_params
params.require(:map).permit(:address, :latitude, :longitude)
end
end
ルーティング
routes.rbにresources :maps
の一行を追加します.
resources :maps
viewファイル
app/views/maps/index.html.erb を作成し, テンプレートとして以下を記述します.
<h2>Google map</h2>
<input id="address" type="textbox" value="">
<input type="button" value="地図を検索" onclick="codeAddress()">
<div id="display">緯度経度が表示されるよ!</div>
<div id='map'></div>
<style>
#map {
height: 400px;
width: 400px;
}
</style>
<script>
let map
const display = document.getElementById('display')
// mapの表示関数
function initMap() {
geocoder = new google.maps.Geocoder()
// mapの初期位置, 縮尺を定義
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 35.6458437,
lng: 139.7046171
},
zoom: 12,
});
// mapsテーブルにあるそれぞれのレコードをmap上に表示
<% @maps.each do |m| %>
(function(){
var contentString = "住所:<%= m.address %>";
// マーカーを立てる
var marker = new google.maps.Marker({
position:{lat: <%= m.latitude %>, lng: <%= m.longitude %>},
map: map,
title: contentString
});
// 情報ウィンドウ(吹き出し)の定義
// 投稿の詳細ページへのリンクも
var infowindow = new google.maps.InfoWindow({
position: {lat: <%= m.latitude %>, lng: <%= m.longitude %>},
content: "<a href='<%= map_url(m.id) %>' target='_blank'><%= m.address %></a>"
});
// クリックしたときに情報ウィンドウを表示
marker.addListener('click', function() {
infowindow.open(map, marker);
});
})();
<% end %>
}
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
});
display.textContent = "検索結果:" + results[ 0 ].geometry.location
} else {
alert('該当する結果がありませんでした:' + status);
}
});
}
</script>
<script
src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap"
async defer>
</script>
<h3>場所投稿フォーム</h3>
<%= form_for(@map, :url => { controller:'maps', action:'create'})do |f| %>
<p>
<%= f.label :address %>
<%= f.text_field :address, size: "50x1" %>
</p>
<%= f.submit "送信"%>
<% end %>
<h3>場所一覧</h3>
<% @maps.each do |t| %>
<p>住所 : <%= t.address %></p>
<p>緯度 : <%= t.latitude %></p>
<p>経度 : <%= t.longitude %></p>
<p><%= link_to "削除する", map_path(t.id), method: :delete %></p>
<hr>
<% end %>
投稿詳細(show)ページでmapを表示する場合は, 上記を参考に自分で作ってみてください!!
その他設定
Gemファイル & 環境変数の設定
Gemfileに以下二つのgemを追記します
gem 'geocoder'
gem 'dotenv-rails'
その後, bundle installします
$ bundle install
geocoderは住所(場所)から緯度経度を取得するGemです.
dotenv-railsは.envファイル(後述)を利用するためのGemです.
Map.rb(モデルファイル)
map.rbファイルは以下のように記述します.
class Map < ApplicationRecord
geocoded_by :address
after_validation :geocode
end
addressが投稿されたら, 自動で緯度経度もデータベースに登録してくれます.
.envファイル
ルートディレクトリーに.envファイルを作成します.
これは, リリースするときに一般に公開したくない類のもの(APIキー)等を管理する用途で用います.
.envファイルにGOOGLE_MAP_API_KEY=xxx
の一行を追記します.
このGOOGLE_MAP_API_KEY=xxx
の
右辺は先ほどメモしておいたGoogleのAPIキーを記述します.
GOOGLE_MAP_API_KEY=ここに自分のAPIキーを書く
これは, maps/index.html.erbの
<script
src="https://maps.googleapis.com/maps/api/js?key=<%= ENV['GOOGLE_MAP_API_KEY'] %>&callback=initMap"
async defer>
</script>
で用いられます.
公開しないように .gitignoreファイルに以下一行を記述します.
/.env
3. herokuにAPIを登録する
herokuにリリースするとき, GoogleのAPIキーをherokuにも登録する必要があります. 以下のxxxを自分のAPIキーに変えて, 実行することを覚えておいてください!
$ heroku config:set GOOGLE_MAP_API_KEY=xxxxxxxxxx