The geocoder: one system, every address

Demo::Geocoder gives each Address a Geolocation in the same slot. It reads the addresses table, so sellers' and customers' addresses are handled in one pass, and it never names User or Company.

Simulated coordinates. Lookups use a short built-in list of city centres (Demo::Gazetteer), nudged per address. No service is called, and the points are not real locations.

Map · 3 located addresses

Geolocation.where(entity: User.all): the component table has no idea what owns a row, so the type comes from the owner's scope.

Simulated geolocations on a world map 3 points in 2 places, listed after the map. Arlington: 1 user Arlington Perth: 2 users Perth · 2

Places on the map

  • Arlington 1 user
  • Perth 2 users

Addresses · 5

An address is waiting when its pair is missing or older than the address. Edit an address on a person's page, come back, and run the geocoder again: only that address is redone. Orders and invoices keep address snapshots with no Geolocation declared, so they are not paired and never geocoded.

OwnerSlotAddressGeolocationState
User Ada Lovelace shipping 12 Ada Lovelace Ln, Perth, WA, 6000, AU -31.94916, 115.86342 Located
User Ada Lovelace billing PO Box 1815, Perth, WA, 6001, AU -31.95135, 115.85640 Located
User Grace Hopper shipping 1 Nanosecond Way, Arlington, VA, 22201, US 38.87964, -77.09338 Located
User Katherine Johnson shipping 1 NASA Dr, Hampton, VA, 23666, US — Place not found
User Alan Turing shipping Hollymeade, Adlington Rd, Wilmslow, SK9 2BT, GB — Waiting for the geocoder

Declared, not configured

Pairing is two declarations in the same slot. The geocoder asks each owner's class whether it declares the pair, so a new entity type joins in without a change to the system.

class User < ApplicationEntity
  component Address,     prefix: :shipping
  component Geolocation, prefix: :shipping
  component Address,     prefix: :billing
  component Geolocation, prefix: :billing
end

class Company < ApplicationEntity
  component Address
  component Geolocation
end

Still one migration

The geolocations table was created by rails g ecs_rails:install along with the rest of the catalogue. Adding the geocoder needed no new table and no migration. db/migrate holds:

20260904080008_ecs_rails_install.rb

Read the geocoder's source on GitHub.