tutorial rails geocoder ruby-on-rails activerecord callback geocoding postgis

ruby on rails - rails - Geocodificación de direcciones con geocoder gem y la base de datos PostGIS con RGeo



geocoder rails 5 (1)

Intento usar la gema geocoder para buscar direcciones y coordenadas. Quiero que funcione junto con mi base de datos espacial PostGIS y la gema RGeo, que utiliza funciones de puntos en lugar de guardar valores de latitud y longitud por separado. Así que he intentado trabajar en mi modelo para guardar los resultados de la búsqueda del geocodificador en una función RGeo POINT:

class Location < ActiveRecord::Base attr_accessible :latlon, :name, :address set_rgeo_factory_for_column(:latlon, RGeo::Geographic.spherical_factory(:srid => 4326)) geocoded_by :name_and_address do |obj, results| if geo = results.first obj.latlon = Location.rgeo_factory_for_column(:latlon).point(geo.longitude, geo.latitude) end end after_initialize :init after_validation :geocode def init self.latlon ||= Location.rgeo_factory_for_column(:latlon).point(0, 0) end def latitude self.latlon.lat end def latitude=(value) lon = self.latlon.lon self.latlon = Location.rgeo_factory_for_column(:latlon).point(lon, value) end def longitude self.latlon.lon end def longitude=(value) lat = self.latlon.lat self.latlon = Location.rgeo_factory_for_column(:latlon).point(value, lat) end def name_and_address "#{self.name}, #{self.address}" end end

En la consola de Rails ahora puedo hacer:

test = Location.new(name: "Eiffel Tower") // => #<Location id: nil, name: "Eiffel Tower", latlon: #<RGeo::Geographic::SphericalPointImpl:0x81579974 "POINT (0.0 0.0)">, created_at: nil, updated_at: nil, address: nil> test.geocode // => #<RGeo::Geographic::SphericalPointImpl:0x81581ac0 "POINT (2.294254 48.858278)">

¡Maravilloso! Sin embargo, cuando quiero guardar mi ubicación de prueba, que desencadena la llamada :after_validation para :geocode :after_validation un error:

NoMethodError: undefined method `lon'' for nil:NilClass from /Users/sg/rails-projects/geo_rails_test/app/models/location.rb:24:in `latitude='' from /Users/sg/rails-projects/geo_rails_test/app/models/location.rb:7:in `block in <class:Location>'' from /Users/sg/.rvm/gems/ruby-1.9.3-p194/gems/geocoder-1.1.2/lib/geocoder/stores/base.rb:108:in `call'' from /Users/sg/.rvm/gems/ruby-1.9.3-p194/gems/geocoder-1.1.2/lib/geocoder/stores/base.rb:108:in `do_lookup'' from /Users/sg/.rvm/gems/ruby-1.9.3-p194/gems/geocoder-1.1.2/lib/geocoder/stores/active_record.rb:278:in `geocode'' from /Users/sg/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `_run__1498365873506454431__validation__51840359655181017__callbacks'' [...]

Parece que la devolución de llamada del código geográfico elimina el objeto RGeo de modo que sus métodos integrados así como mis métodos getter y setter ya no estén disponibles. ¿Por qué? ¿Algunas ideas?


Fue un error sangriento ...

Funciona. Lo dejo, tal vez alguien más tenga el mismo problema o una mejor solución ...

También he agregado el caso reverse_geocode .

Ahora mira lo que puede hacer:

1.9.3p194 :310 > loc = Location.new(name: "Vatikan") => #<Location id: nil, name: "Vatikan", latlon: #<RGeo::Geographic::SphericalPointImpl:0x8148add8 "POINT (0.0 0.0)">, created_at: nil, updated_at: nil, address: nil> 1.9.3p194 :311 > loc.save (0.2ms) BEGIN SQL (0.6ms) INSERT INTO "locations" ("address", "created_at", "latlon", "name", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["address", "Via Pio X, 00120, Vatican City"], ["created_at", Sat, 17 Nov 2012 19:26:59 UTC +00:00], ["latlon", #<RGeo::Geographic::SphericalPointImpl:0x81570554 "POINT (12.453389 41.902916)">], ["name", "Vatikan"], ["updated_at", Sat, 17 Nov 2012 19:26:59 UTC +00:00]] (0.9ms) COMMIT => true

¡Me encanta esto! :-)