2012-11-17 73 views
6

RGeo爲POINT特徵提供了內置方法,例如吸氣方法lat()lon()可從POINT對象中提取經度和緯度值。不幸的是,這些不作爲制定者。例如:爲RGeo點設置單個座標

point = RGeo::Geographic.spherical_factory(:srid => 4326).point(3,5)  // => #<RGeo::Geographic::SphericalPointImpl:0x817e521c "POINT (3.0 5.0)"> 

我可以這樣做:

point.lat  // => 5.0 
point.lon  // => 3.0 

但我不能這樣做:

point.lat = 4 // => NoMethodError: undefined method `lat=' for #<RGeo::Geographic::SphericalPointImpl:0x00000104024770> 

任何建議,如何實現setter方法?你會在模型中使用它還是擴展Feature類?

回答

27

我RGeo的作者,因此可以考慮在此基礎上這個答案權威性。

總之,請避免做到這一點。 RGeo對象故意沒有setter方法,因爲它們是不可變對象。這是爲了使它們可以被緩存,用作散列鍵,跨線程使用等。一些RGeo計算假設特性對象的值永遠不會改變,因此進行這樣的更改可能會產生意想不到的和不可預知的後果。

如果您確實想要「更改」的值,請創建一個新對象。例如:

p1 = my_create_a_point() 
p2 = p1.factory.point(p1.lon + 20.0, p2.lat) 
+0

感謝澄清這一點,丹尼爾。 – donsteffenski

+3

總是很有趣,閱讀以「我是你問的關於圖書館的作者」開頭的答案。偉大的:) – SpacyRicochet

2

我發現了一些可行的方法,雖然可能會有更優雅的解決方案。

在我Location模型我已經加入提綱方法:

after_initialize :init 


    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 
+0

當我運行這個,我看到#未定義的方法'rgeo_factory_for_column'#' – mkirk

0

我落得這樣做在我的模型是這樣的:

class MyModel < ActiveRecord::Base 

    attr_accessor :longitude, :latitude 
    attr_accessible :longitude, :latitude 

    validates :longitude, numericality: { greater_than_or_equal_to: -180, less_than_or_equal_to: 180 }, allow_blank: true 
    validates :latitude, numericality: { greater_than_or_equal_to: -90, less_than_or_equal_to: 90 }, allow_blank: true 

    before_save :update_gps_location 

    def update_gps_location 
    if longitude.present? || latitude.present? 
     long = longitude || self.gps_location.longitude 
     lat = latitude || self.gps_location.latitude 
     self.gps_location = RGeo::Geographic.spherical_factory(srid: 4326).point(long, lat) 
    end 
    end 
end 

然後,你可以更新的位置,像這樣:

my_model.update_attributes(longitude: -122, latitude: 37) 

我沒有加載在after_initialize塊中增加經度/緯度,因爲在我的應用程序中,我們永遠不需要讀取數據,只需寫入它。你可以很容易地添加,但。

貸記this answer驗證。