2012-11-17 36 views
9

Tôi đang cố gắng sử dụng đá quý mã hóa địa lý để tra cứu địa chỉ và tọa độ. Tôi muốn nó hoạt động cùng với cơ sở dữ liệu không gian PostGIS của tôi và đá quý RGeo, sử dụng các tính năng POINT thay vì lưu các giá trị vĩ độ và kinh độ một cách riêng biệt. Vì vậy, tôi đã cố gắng để làm việc vào mô hình của tôi để lưu các kết quả từ tra cứu geocoder vào một tính năng POINT RGeo:Mã hóa địa lý địa chỉ với mã hóa địa lý và cơ sở dữ liệu PostGIS với 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 

Trong Rails console bây giờ tôi có thể làm:

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

tuyệt vời! Tuy nhiên, khi tôi muốn lưu bài kiểm tra vị trí của mình, mà gây nên các :after_validation gọi cho :geocode tôi nhận được một lỗi:

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

Dường như callback geocode xóa các đối tượng RGeo để nó được xây dựng trong các phương pháp cũng như phương thức getter và setter của tôi không còn nữa. Tại sao? Bất kỳ ý tưởng?

Trả lời

6

Đó là một lỗi đánh máy ...

Nó hoạt động. Tôi để nó lên, có thể ai đó khác có cùng một vấn đề hoặc giải pháp tốt hơn ...

Tôi cũng đã thêm trường hợp reverse_geocode.

Bây giờ hãy nhìn những gì nó có thể làm:

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 

Tôi yêu này! :-)

Các vấn đề liên quan