MapkickJS is a javascript adapter to display coordinates on Mapbox maps. It requires a Mapbox API key.

mapkick-rb is a Ruby on Rails adapter for MapkickJS. It allows you to easily feed a JSON with coordinates and display a map within your Rails app.

To display a marker on a map, you need to know latitude and longitude GPS coordinates. gem Geocoder allows you to get coordinates based on an address (house, street, city, state, country).

Basic usage

After installing the gem, initialize your Mapkick API key.

# echo > config/initializers/mapbox.rb
# config/initializers/mapbox.rb
ENV["MAPBOX_ACCESS_TOKEN"] = "pk.eyJ1..."
# ENV["MAPBOX_ACCESS_TOKEN"] = Rails.application.credentials.dig(:mapkick_api_key)

Basic map with multiple options:

<%= js_map [{latitude: 37.7829,
             longitude: -122.4190,
             label: 'My home',
             tooltip: 'Hello!'
            }],
            id: "cities-map",
            width: "800px",
            height: "500px",
            markers: {color: "#00FF00"},
            tooltips: { hover: false, html: true},
            style: "mapbox://styles/mapbox/outdoors-v12",
            zoom: 15,
            controls: true,
            refresh: 60 %>

Result - display a marker on draggable map:

mapbox-map-all-params

HTML tooltips

Create a helper with a link to the location page:

# app/helpers/locations_helper.rb
module LocationsHelper
  def html_link_to_location(location)
    link_to location.name,
            location_url(location),
            target: '_blank',
            style: 'font-weight: bold; color: green'
  end
end

To be able to click on the tooltip, use the option { hover: false, html: true}.

Render the helper method in the tooltip param:

<%= js_map [{latitude: location.latitude,
             longitude: location.longitude,
             label: location.name,
             tooltip: html_link_to_location(location)}],
             tooltips: { hover: false, html: true} %>

Result - map with clickable links to locations:

mapbox-map-clickable-link

Display multiple locations on the map, JSON

For this, the best way will be to render /locations.json:

<%= js_map locations_path(format: :json) %>

Customize the JSON:

// app/views/locations/_location.json.jbuilder
json.extract! location, :latitude, :longitude
json.label location.name
json.tooltip html_link_to_location(location)
// json.tooltip "#{html_link_to_location(location)} <br> #{location.address}"

Result - @locations is rendered from app/views/locations/index.json.jbuilder:

mapbox-map-multiple-locations

JSON with search params

In this final example, we will factor in having a search form for place and distance. Bigger distance -> smaller zoom:

# app/controllers/locations_controller.rb
class LocationsController < ApplicationController
  before_action :set_location, only: %i[ show edit update destroy ]

  # GET /locations or /locations.json
  def index
    if params[:place].present?
      @locations = Location.near(params[:place], params[:distance] || 10, order: :distance)
      # distance 10 km => zoom 13x; distance 100 km => zoom 10x;
      @zoom = params[:distance].eql?('10') ? 13 : 10
    else
      @locations = Location.all
    end
    respond_to do |format|
      format.html
      format.json
    end
  end

Be sure to add the query params to the path in the view:

<%= js_map locations_path(format: :json, place: params[:place], distance: params[:distance]), zoom: @zoom %>

Result - smaller/bigger map zoom based on search params:

geocoder-search-zoom

That’s it! Now you can build your own AIRNBN search frontend!