2023-05-31 - Geocoding and Maps

main topics


Geocode: translates an address into coordinates.


install & config

geocoded_by :address
after_validation :geocode, if: :will_save_change_to_address?



def index
  @flats = Flat.all
  @markers = @flats.geocoded.map do |flat|
      lat: flat.latitude,
      lng: flat.longitude


rails new \
  -d postgresql \
  -j webpack \
  -m https://raw.githubusercontent.com/lewagon/rails-templates/master/minimal.rb \
cd rails-geocoding

# CRUD for a flat
# rails scaffold # To be done...

Ruby Gem for Geocoding:

bundle add geocoder
rails generate geocoder:config
# creates 'config/initializers/geocoder.rb'

In the config/initializers/geocoder.rb, change units: to use :km.

Change lookup if you want to customize the service that will do the geocoding (default is nominatim).

We need coordinates in our DB Table/Model:

rails generate migration \
  AddCoordinatesToFlats latitude:float longitude:float
rails db:migrate

Update the model

geocoded_by :address
after_validation :geocode, if: :will_save_change_to_address?

Use mapbox for displaying a map. Get your API token and save it in the .env file (don't forget to put .env* in your .gitignore).

mapbox docs: https://docs.mapbox.com/mapbox-gl-js/guides/install/#quickstart

<!-- app/views/layouts/application.html.erb -->
<link href="https://api.mapbox.com/mapbox-gl-js/v2.11.0/mapbox-gl.css" rel="stylesheet">
<the-script src="https://api.mapbox.com/mapbox-gl-js/v2.11.0/mapbox-gl.js"></the-script>
<!-- rename the-script into script after copy-paste -->

13:30 - Edit Rails controller

16:00 - put a map in the view. Mapbox GL JS Installation Guide: https://docs.mapbox.com/mapbox-gl-js/guides/install/

17:30 - generate a stimulus controller

20:20 - pass the api key to the stimulus controller


22:00 - in the stimulus controller, customize the center array according to the current browser location.

navigator.geolocation.getCurrentPosition((data) => {
 console.log(data.coords.latitude, data.coords.longitude)

23:50 - how to create a marker

30:00 - sending @markers from the controller to the view.

35:00 - fit map to markers

#fitMapToMarkers() {
  const bounds = new mapboxgl.LngLatBounds();
  this.markersValue.forEach(marker => bounds.extend([marker.lng, marker.lat ]))
  this.map.fitBounds(bounds, { padding: 70, maxZoom: 15, duration: 0 })

41:10 - pass api key to heroku

heroku config:set MAPBOX_API_KEY=...

41:30 - pass more info to the view
- 47:40 - enrich the data in the @markers being created in the Flat controller
- create a partial

49:30 - custom marker

56:20 - searching on the map - REALLY COOL

59:28 - styling your map

1:00:00 - address autocomplete