2012-11-17 35 views
6

RGeo cung cấp các phương thức tích hợp cho các tính năng POINT, ví dụ phương thức getter lat()lon() để kéo các giá trị vĩ độ và kinh độ từ đối tượng POINT. Thật không may, chúng không hoạt động như những người định cư. Ví dụ:Đặt tọa độ đơn cho RGeo Point

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

tôi có thể làm điều này:

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

Nhưng tôi không thể làm:

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

Bất kỳ lời đề nghị như thế nào để thực hiện phương pháp setter? Bạn sẽ làm điều đó trong Model hoặc mở rộng lớp Feature?

Trả lời

27

Tôi là tác giả của RGeo, vì vậy bạn có thể xem xét câu trả lời này có thẩm quyền trên cơ sở đó.

Tóm lại, XIN VUI LÒNG TRÁCH NHIỆM NÀY. Các đối tượng RGeo cố tình không có phương thức setter vì chúng có nghĩa là những vật thể bất biến. Một số tính toán của RGeo giả định rằng giá trị của đối tượng feature sẽ không bao giờ thay đổi, vì vậy việc thay đổi như thế này có thể có những hậu quả bất ngờ và không lường trước được.

Nếu bạn thực sự muốn có giá trị "đã thay đổi", hãy tạo đối tượng mới. Ví dụ:

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

Cảm ơn bạn đã làm rõ điều này, Daniel. – donsteffenski

+3

Luôn vui vẻ khi đọc câu trả lời bắt đầu bằng "Tôi là tác giả của thư viện bạn đang đặt câu hỏi về". Tuyệt quá :) – SpacyRicochet

2

Tôi đã tìm thấy thứ gì đó hoạt động, mặc dù có thể có nhiều giải pháp thanh lịch hơn.

Trong phương pháp luận Location mô hình tôi đã thêm tôi:

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

Khi tôi chạy điều này, tôi thấy 'phương pháp không xác định' rgeo_factory_for_column 'cho # ' – mkirk

0

tôi đã kết thúc làm điều gì đó như thế này trong mô hình của tôi:

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 

Sau đó, bạn chỉ có thể cập nhật vị trí như vậy:

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

tôi không tải lên kinh độ/vĩ độ trong một khối after_initialize bởi vì trong ứng dụng của tôi, chúng tôi không bao giờ cần phải đọc dữ liệu, chỉ viết nó. Bạn có thể dễ dàng thêm rằng mặc dù.

Tín dụng cho this answer để xác thực.

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