2012-11-17 4 views
9

Ich versuche, den Geocoder-Edelstein zum Nachschlagen von Adressen und Koordinaten zu verwenden. Ich möchte, dass es mit meiner PostGIS-Spatial-Datenbank und dem RGeo-Juwel zusammenarbeitet, das POINT-Funktionen verwendet, anstatt Breiten- und Längengrad separat zu speichern. Also habe ich versucht, in mein Modell arbeiten, um die Ergebnisse aus dem Geocoder-Lookup in eine RGEO POINT-Funktion zu speichern:Geocoding-Adressen mit Geocoder-Edelstein und PostGIS-Datenbank mit RGeo

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 

In der Rails-Konsole kann ich jetzt tun:

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)"> 

Wonderful! Allerdings, wenn ich meinen Test Ort speichern möge, die den :after_validation Ruf nach :geocode lösen bekomme ich einen Fehler:

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' 
    [...] 

Es scheint, dass die Geocodierung Rückruf so das RGEO Objekt löscht, dass sein in Methoden und gebaut als Meine Getter- und Setter-Methoden sind nicht mehr verfügbar. Warum? Irgendwelche Ideen?

Antwort

6

Es war ein blutiger Tippfehler ...

Es funktioniert. Ich lasse es oben, vielleicht hat jemand anderes das gleiche Problem oder eine bessere Lösung ...

Ich habe auch den reverse_geocode Fall hinzugefügt. Jetzt

schauen, was es tun kann:

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 

I love this! :-)