dawarich/app/services/reverse_geocoding/places/fetch_data.rb

100 lines
2.9 KiB
Ruby
Raw Normal View History

2024-08-05 15:23:08 -04:00
# frozen_string_literal: true
# This class uses Komoot's Photon API
2024-08-05 15:23:08 -04:00
class ReverseGeocoding::Places::FetchData
attr_reader :place
IGNORED_OSM_VALUES = %w[house residential yes detached].freeze
IGNORED_OSM_KEYS = %w[highway railway].freeze
2024-08-05 15:23:08 -04:00
def initialize(place_id)
@place = Place.find(place_id)
end
def call
unless DawarichSettings.reverse_geocoding_enabled?
Rails.logger.warn('Reverse geocoding is not enabled')
2024-08-05 15:23:08 -04:00
return
end
first_place = reverse_geocoded_places.shift
2024-08-05 15:23:08 -04:00
update_place(first_place)
reverse_geocoded_places.each { |reverse_geocoded_place| fetch_and_create_place(reverse_geocoded_place) }
2024-08-05 15:23:08 -04:00
end
private
def update_place(reverse_geocoded_place)
return if reverse_geocoded_place.nil?
data = reverse_geocoded_place.data
2024-08-05 15:23:08 -04:00
place.update!(
name: place_name(data),
2025-03-03 15:34:06 -05:00
lonlat: "POINT(#{data['geometry']['coordinates'][0]} #{data['geometry']['coordinates'][1]})",
city: data['properties']['city'],
country: data['properties']['country'],
geodata: data,
source: Place.sources[:photon],
2024-08-12 16:18:11 -04:00
reverse_geocoded_at: Time.current
2024-08-05 15:23:08 -04:00
)
end
def fetch_and_create_place(reverse_geocoded_place)
data = reverse_geocoded_place.data
new_place = find_place(data)
2024-08-12 16:18:11 -04:00
new_place.name = place_name(data)
new_place.city = data['properties']['city']
new_place.country = data['properties']['country']
new_place.geodata = data
new_place.source = :photon
if new_place.lonlat.blank?
new_place.lonlat = "POINT(#{data['geometry']['coordinates'][0]} #{data['geometry']['coordinates'][1]})"
end
2024-08-12 16:18:11 -04:00
new_place.save!
2024-08-05 15:23:08 -04:00
end
def find_place(place_data)
found_place = Place.where(
"geodata->'properties'->>'osm_id' = ?", place_data['properties']['osm_id'].to_s
).first
2024-08-12 16:18:11 -04:00
return found_place if found_place.present?
2024-08-12 16:18:11 -04:00
Place.find_or_initialize_by(
2025-03-03 15:34:06 -05:00
lonlat: "POINT(#{place_data['geometry']['coordinates'][0].to_f.round(5)} #{place_data['geometry']['coordinates'][1].to_f.round(5)})",
latitude: place_data['geometry']['coordinates'][1].to_f.round(5),
longitude: place_data['geometry']['coordinates'][0].to_f.round(5)
2024-08-12 16:18:11 -04:00
)
end
def place_name(data)
name = data.dig('properties', 'name')
type = data.dig('properties', 'osm_value')&.capitalize&.gsub('_', ' ')
address = "#{data.dig('properties', 'postcode')} #{data.dig('properties', 'street')}"
address += " #{data.dig('properties', 'housenumber')}" if data.dig('properties', 'housenumber').present?
name ||= address
"#{name} (#{type})"
end
def reverse_geocoded_places
data = Geocoder.search(
2025-03-03 14:50:49 -05:00
[place.lat, place.lon],
limit: 10,
distance_sort: true,
radius: 1,
units: ::DISTANCE_UNIT
)
data.reject do |place|
place.data['properties']['osm_value'].in?(IGNORED_OSM_VALUES) ||
place.data['properties']['osm_key'].in?(IGNORED_OSM_KEYS)
end
end
2024-08-05 15:23:08 -04:00
end