Plotting Points on a Map from Scratch

Episode #86 by Teacher's Avatar David Kimura

Summary

Using the Google Maps Javascript API, learn how to plot markers onto a map. Load markers and info windows through AJAX calls to your Rails JSON API.
rails javascript api maps view ajax 8:33

Resources

Summary

# routes.rb
resources :stores do
  resources :operation_hours
  collection do 
    get :map
  end
end

# stores/maps.html.erb
<h1>Maps</h1>
<div id='map'></div>

# layouts/application.html.erb
<%= tag :meta, name: 'google_maps', content: 'YOUR_API_KEY' %>

# application.js
$(document).on('turbolinks:load', function(){
  if ($('#map').length > 0){
    var google_map = $('meta[name=google_maps]').attr("content");
    $.getScript(`https://maps.googleapis.com/maps/api/js?key=${google_map}&callback=initMap`);
  }
})

# stores.coffee
@initMap = ->
  center = 
    lat: 0
    lng: 0

  map = new (google.maps.Map) $('#map')[0],
    zoom: 2
    center: center

  infowindow = new (google.maps.InfoWindow)

  $.getJSON '/stores.json', (jsonData) ->
    $.each jsonData, (key, data) ->
      latLng = new (google.maps.LatLng)(data.lat, data.lng)
      marker = new (google.maps.Marker)
        position: latLng
        map: map
        title: data.title
      google.maps.event.addListener marker, 'click', ->
        infowindow.setOptions
          content: data.content
          maxWidth: 300
        infowindow.open map, marker

# stores/index.json.jbuilder
json.array! @stores do |store|
  json.lat store.latitude
  json.lng store.longitude
  json.title store.name
  json.content StoresController.render(partial: 'stores/store', locals: { store: store }, format: :html).squish
end

# stores/_store.html.erb
<h1><%= store.name %></h1>
<h2>Hours of Operation</h2>
<ul>
  <% store.operation_hours.each do |operation_hour| %>
    <li><strong><%= operation_hour.day.titleize %></strong> - <%= operation_hour.hours %></li>
  <% end %>
</ul>

# stores_controller.rb
class StoresController < ApplicationController
  ...
  def index
    @stores = Store.includes(:operation_hours).all
  end
  ...
end