Using Google Maps API (v3) with Rails (5.2)

Paulo Belo
Sep 22, 2018 · 9 min read

Step-by-Step Tutorial

Image for post
Image for post

Setup Rails

Please confirm that you have rails >= 5.2 installed (so you can use Rails Credentials)

rails new gmaps-rails-example
cd gmaps-rails-example
  • latitude: decimal
  • longitude: decimal
Place.create!([
{ "name": "Buckingham Palace", "latitude": "51.501564","longitude": "-0.141944"},
{ "name": "Westminster Abbey", "latitude": "51.499581", "longitude": "-0.127309"},
{ "name": "Big Ben", "latitude": "51.500792", "longitude": "-0.124613"}
])
Image for post
Image for post

Google Maps API and Rails Credentials

Now we’ll setup rails to use the key. To protect our key let’s use Rails Credentials. For more information about Rails Credentials click here

Using Google Maps Static API

Google says:

Image for post
Image for post
<p>
<%= image_tag "https://maps.googleapis.com/maps/api/staticmap?zoom=17&size=400x300&center=#{@place.latitude},#{@place.longitude}&key=#{Rails.application.credentials.google_maps_api_key}", alt: "Map" %>
</p>
Image for post
Image for post

Adding a marker

And now we’ll insert a marker. Replace this part of the code:

<p>
<%= image_tag "https://maps.googleapis.com/maps/api/staticmap?zoom=17&size=400x300&markers=size:small%7Ccolor:red%7C#{@place.latitude},#{@place.longitude}&key=#{Rails.application.credentials.google_maps_api_key}", alt: "Map" %>
</p>
Image for post
Image for post

Using Google Maps Javascript API

We must start by inserting the code that loads the api in our page. To do so, edit app/views/layouts/application.html.erb and insert it in the <head>, before 'application' because it must be loaded before our code that will be included trough 'application' manifest.

...
<%= javascript_include_tag 'https://maps.googleapis.com/maps/api/js?key='+Rails.application.credentials.google_maps_api_key %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
...
<p>
<div id="map"></div>
</p>
#map {
width: 600px;
height: 400px;
}
...
<%= yield(:head_tags) %>
</head>
...
<% provide :head_tags do %>
<script>
document.addEventListener("DOMContentLoaded", function(){
initMap(<%=@place.latitude%>, <%=@place.longitude%>)
});
</script>
<% end %>
function initMap(lat, lng) {    var myCoords = new google.maps.LatLng(lat, lng);    var mapOptions = {
center: myCoords,
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
Image for post
Image for post
var marker = new google.maps.Marker({
position: myCoords,
map: map
});
function initMap(lat, lng) {    var myCoords = new google.maps.LatLng(lat, lng);    var mapOptions = {
center: myCoords,
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map'), mapOptions); var marker = new google.maps.Marker({
position: myCoords,
map: map
});
}
Image for post
Image for post
<% provide :head_tags do %>
<meta name='turbolinks-visit-control' content='reload'>
<script>
document.addEventListener("DOMContentLoaded", function(){
initMap(<%=@place.latitude%>, <%=@place.longitude%>)
});
</script>
<% end %>
...

Using Map to get values

When we create a ‘New Place’ or ‘Edit’ an existing one, Rails will use the partial _form.html.erb.

<% provide :head_tags do %>
<meta name='turbolinks-visit-control' content='reload'>
<script>
document.addEventListener("DOMContentLoaded", initMap2);
</script>
<% end %>
<p>
<div id="map2"></div>
</p>
#map2 {
width: 600px;
height: 400px;
}
function initMap2() {    var lat = document.getElementById('place_latitude').value;
var lng = document.getElementById('place_longitude').value;

var myCoords = new google.maps.LatLng(lat, lng);
var mapOptions = {
center: myCoords,
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map2'), mapOptions); var marker = new google.maps.Marker({
position: myCoords,
animation: google.maps.Animation.DROP,
map: map,
draggable: true
});
}
// refresh marker position and recenter map on marker
function refreshMarker(){
var lat = document.getElementById('place_latitude').value;
var lng = document.getElementById('place_longitude').value;
var myCoords = new google.maps.LatLng(lat, lng);
marker.setPosition(myCoords);
map.setCenter(marker.getPosition());
}
// when input values change call refreshMarker
document.getElementById('place_latitude').onchange = refreshMarker;
document.getElementById('place_longitude').onchange = refreshMarker;
// when marker is dragged update input values
marker.addListener('drag', function() {
latlng = marker.getPosition();
newlat=(Math.round(latlng.lat()*1000000))/1000000;
newlng=(Math.round(latlng.lng()*1000000))/1000000;
document.getElementById('place_latitude').value = newlat;
document.getElementById('place_longitude').value = newlng;
});
// When drag ends, center (pan) the map on the marker position
marker.addListener('dragend', function() {
map.panTo(marker.getPosition());
});
Image for post
Image for post
// if not defined create default position
if (!lat || !lng){
lat=51.5;
lng=-0.125;
document.getElementById('place_latitude').value = lat;
document.getElementById('place_longitude').value = lng;
}
function initMap2() {    var lat = document.getElementById('place_latitude').value;
var lng = document.getElementById('place_longitude').value;

// if not defined create default position
if (!lat || !lng){
lat=51.5;
lng=-0.125;
document.getElementById('place_latitude').value = lat;
document.getElementById('place_longitude').value = lng;
}
var myCoords = new google.maps.LatLng(lat, lng); var mapOptions = {
center: myCoords,
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map2'), mapOptions); var marker = new google.maps.Marker({
position: myCoords,
animation: google.maps.Animation.DROP,
map: map,
draggable: true
});
// refresh marker position and recenter map on marker
function refreshMarker(){
var lat = document.getElementById('place_latitude').value;
var lng = document.getElementById('place_longitude').value;
var myCoords = new google.maps.LatLng(lat, lng);
marker.setPosition(myCoords);
map.setCenter(marker.getPosition());
}
// when input values change call refreshMarker
document.getElementById('place_latitude').onchange = refreshMarker;
document.getElementById('place_longitude').onchange = refreshMarker;
// when marker is dragged update input values
marker.addListener('drag', function() {
latlng = marker.getPosition();
newlat=(Math.round(latlng.lat()*1000000))/1000000;
newlng=(Math.round(latlng.lng()*1000000))/1000000;
document.getElementById('place_latitude').value = newlat;
document.getElementById('place_longitude').value = newlng;
});
// When drag ends, center (pan) the map on the marker position
marker.addListener('dragend', function() {
map.panTo(marker.getPosition());
});
}

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store