Work
with us

Tell us about your idea
and we will find a way
to make it happen.

Get estimate

Join our awesome team

Check offers

We live in times where graphical visualization is used for everything. While presenting most of the things we try to use images, which are absorbed much easier than plain text by the common user. One of the best examples are addresses – we focus more attention on the point selected on the map than on the regular text address. That’s because a map reference gives us more information than just the text address that you may have never heard before. Today’s entry will be focused on Google Maps, which, as you probably know, is the most popular web mapping technology.

  • As an example we’ll take a company model. The our goals are:
    • Creating a company – put marker on the map
    • Editing the company – change localization of the existing company
    • Show company – show the localization on the map

But before we start you need to log in to your google account and generate your own API_KEY on that page

Preparing the application

Firstly we create a simple Company model in database, which contains the name and map coordinates.

rails generate model Company name:string lat:decimal lng:decimal
rails db:migrate

Secondly generate a controller with the necessary actions for it

rails generate controller companies index show new edit

After that, we’ll need to add Gmaps4rails gem to the application’s Gemfile

gem 'gmaps4rails'

as well as some javascript dependencies (GoogleMaps API) to the head block

%script{src: '//maps.google.com/maps/api/js?key=[AIzaSyCZE5WjsS3K7nbA8ojw8nOLzDIApbYjD0Y]'}
%script{src: '//cdn.rawgit.com/mahnunchik/markerclustererplus/master/dist/markerclusterer.min.js'}
%script{src: '//cdn.rawgit.com/printercu/google-maps-utility-library-v3-read-only/master/infobox/src/infobox_packed.js', type: 'text/javascript'}

finally we have to download Underscore.JS and copy it to assets/javascripts.

Now we are ready to use the powerful opportunities of Google Maps in Rails!

Programming maps

Most importantly, we have to create the javascript logic for our maps. We will create two types of maps – the first for a company card (show view), where we can only see the location of a company, and the second for the forms (new and edit views), where we also can place a marker to indicate the address. To do that, we need to create the javascipt file in the assets folder. We’ll need to write two functions (the first only to print marker and the second to print an existent location and give the possibility of creating a new one).

The 1st map init function – for a company card (with validation for companies without coordinates):

function gmap_show(company) {
  if ((company.lat == null) || (company.lng == null) ) {    // validation check if coordinates are there
    return 0;
  }

  handler = Gmaps.build('Google');    // map init
  handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
    markers = handler.addMarkers([    // put marker method
      {
        "lat": company.lat,    // coordinates from parameter company
        "lng": company.lng,
        "picture": {    // setup marker icon
          "url": 'http://bounceworld.co.za/bounceworld/wp-content/uploads/2015/10/map_marker.png',
          "width":  32,
          "height": 32
        },
        "infowindow": "<b>" + company.name + "</b> " + company.address + ", " + company.postal_code + " " + company.city
      }
    ]);
    handler.bounds.extendWith(markers);
    handler.fitMapToBounds();
    handler.getMap().setZoom(12);    // set the default zoom of the map
  });
}

The 2nd map init function – for company forms (new and edit views) Validation checks if we are using an edit, or a new view. If we are creating a new record – we do not have any marker on our map and we only have the ability to put a new one, if we are updating a record – we will have an existent marker and we’ll be able to change it.

function gmap_form(company) {
  handler = Gmaps.build('Google');    // map init
  handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
    if (company && company.lat && company.lng) {    // statement check - new or edit view
      markers = handler.addMarkers([    // print existent marker
        {
          "lat": company.lat,
          "lng": company.lng,
          "picture": {
            "url": 'http://bounceworld.co.za/bounceworld/wp-content/uploads/2015/10/map_marker.png',
            "width":  32,
            "height": 32
          },
          "infowindow": "<b>" + company.name + "</b> " + company.address + ", " + company.postal_code + " " + company.city
        }
      ]);
      handler.bounds.extendWith(markers);
      handler.fitMapToBounds();
      handler.getMap().setZoom(12);
    }
    else {    // show the empty map
      handler.fitMapToBounds();
      handler.map.centerOn([52.10, 19.30]);
      handler.getMap().setZoom(6);
    }
  });

  var markerOnMap;

  function placeMarker(location) {    // simply method for put new marker on map
    if (markerOnMap) {
      markerOnMap.setPosition(location);
    }
    else {
      markerOnMap = new google.maps.Marker({
        position: location,
        map: handler.getMap()
      });
    }
  }

  google.maps.event.addListener(handler.getMap(), 'click', function(event) {    // event for click-put marker on map and pass coordinates to hidden fields in form
    placeMarker(event.latLng);
    document.getElementById("map_lat").value = event.latLng.lat();
    document.getElementById("map_lng").value = event.latLng.lng();
  });
}

Allocating maps in views

At first we have to pass the company as a parameter in controller – standard Ruby stuff

def show
    @company = Company.find(params[:id])
  end

  ...

  private

  def company_params
    params.require(:company).permit(:name, :lat, :lng)
  end
end

and then we can allocate the maps in views. In each we’ll have to pass the ruby variable @company to javascript (using json) and pass the coordinates by hidden field to form.

%h1=@company.name
%p
  lat:
  =@company.lat
%p
  lng:
  =@company.lng
/ map div
#map{:style => "width: 550px; height: 350px;"}

:javascript
  $(document).ready(function(){
    var company = #{@company.to_json}    // pass ruby variable to javascript
    gmap_show(company);    // init show map for company card (only print marker)
  });
%h1 Create company

= form_for @company do |f|
  = f.label :name, 'Nazwa firmy'
  = f.text_field :name
  / map div
  #map{:style => "width: 550px; height: 350px;"}
  = f.hidden_field :lat, id: 'map_lat'
  = f.hidden_field :lng, id: 'map_lng'
  = f.submit 'CREATE'

:javascript
  $(document).ready(function(){
    gmap_form(null);    // form map for new view (print nothing with possibility of put marker)
  });
%h1 Edit company

= form_for @company do |f|
  = f.label :name, 'Company name'
  = f.text_field :name
  / map div
  #map{:style => "width: 550px; height: 350px;"}
  = f.hidden_field :lat, id: 'map_lat'
  = f.hidden_field :lng, id: 'map_lng'
  = f.submit 'UPDATE'

:javascript
  $(document).ready(function(){
    var company = #{@company.to_json}
    gmap_form(company);    // form map for edit view (print marker and possibility of put newer)
  });

Effects

While creating a new company we can put a marker to select the location (though it is not obligatory)

When we’re editing an existing company we can change it’s location on the map

The final result – a company card – users have a good, clear view of where the company is located – on the map!

This is just a small piece of the robust functionality of Google Maps. Good luck in discovering more!

Post tags: