7

RGeo 为 POINT 功能提供内置方法,例如 getter 方法lat()以及lon()从 POINT 对象中提取纬度和经度值。不幸的是,这些不能作为二传手。例如:

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 方法的任何建议?您会在模型中执行此操作还是扩展要素类?

4

3 回答 3

32

我是 RGeo 的作者,因此您可以在此基础上将此答案视为权威。

简而言之,请避免这样做。RGeo 对象故意没有设置方法,因为它们是不可变对象。这样它们就可以被缓存、用作哈希键、跨线程使用等。一些 RGeo 计算假设特征对象的值永远不会改变,因此进行这样的更改可能会产生意想不到和不可预测的后果。

如果您真的想要一个“更改”的值,请创建一个新对象。例如:

p1 = my_create_a_point()
p2 = p1.factory.point(p1.lon + 20.0, p2.lat)
于 2012-11-27T07:13:28.610 回答
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
于 2012-11-17T18:29:26.583 回答
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 块中加载经度/纬度,因为在我的应用程序中,我们永远不需要读取数据,只需写入即可。你可以很容易地添加它。

归功于此答案的验证。

于 2013-05-10T22:22:53.700 回答