RGeo错误:尝试从纬度/经度创建点时出错。

3
我正在编写一款应用程序,尝试将一些通用的地理定位功能集成到其中,包括将一些纬度/经度坐标保存为数据库中的点。这样做的目的是允许用户使用他们的位置(由设备提供)或谷歌地图标记来选择他们的坐标。 我已经成功地从地图或设备获取了坐标,但现在我遇到了一个问题,就是如何从它们创建一个点以保存到数据库中。
我已经阅读了文档,并尝试将以下代码添加到我的初始化器中:

initializer/rgeo.rb

require 'rgeo-activerecord' 

RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config|
  # By default, use the GEOS implementation for spatial columns.
  config.default = RGeo::Geos.factory_generator

  # But use a geographic implementation for point columns.
  config.register(RGeo::Geographic.spherical_factory(srid: 4326), geo_type: "point")
end

Gemfile:

gem 'activerecord-postgis-adapter'

gem 'rgeo'

gem 'rgeo-activerecord'

迁移:

def change
 add_column :monuments, :grid_ref, :point, geographic: true
end

当尝试创建一个点时,我在rails控制台中遇到了这个错误:

irb(main):004:0> m.grid_ref = "POINT(-122.193963 47.675086)"
ArgumentError: invalid value for Float(): "POINT(-122.193963 47.675086)"
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/oid/point.rb:20:in `Float'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/oid/point.rb:20:in `block in type_cast'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/oid/point.rb:20:in `map'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/oid/point.rb:20:in `type_cast'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql/oid/point.rb:18:in `type_cast'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/type/value.rb:23:in `type_cast_from_database'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/type/mutable.rb:5:in `type_cast_from_user'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute.rb:100:in `type_cast'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute.rb:42:in `original_value'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute.rb:37:in `value'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute.rb:46:in `value_for_database'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:164:in `store_original_raw_attribute'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:93:in `write_attribute'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activerecord-4.2.0/lib/active_record/attribute_methods.rb:50:in `__temp__76279646f5275666'
    from (irb):4
    from /usr/local/lib/ruby/gems/2.2.0/gems/railties-4.2.0/lib/rails/commands/console.rb:110:in `start'
... 9 levels...
    from /usr/local/lib/ruby/gems/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /usr/local/lib/ruby/gems/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/commands/rails.rb:6:in `call'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/command_wrapper.rb:38:in `call'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:185:in `block in serve'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:156:in `fork'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:156:in `serve'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:131:in `block in run'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:125:in `loop'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application.rb:125:in `run'
    from /usr/local/lib/ruby/gems/2.2.0/gems/spring-1.6.4/lib/spring/application/boot.rb:18:in `<top (required)>'
    from /usr/local/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /usr/local/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:55:in `require'

我阅读了这篇文章后,采用了这种方法,该文章建议模型能够隐式地理解WKT字符串,并将其内部转换为“点”对象。


你最终解决了吗?我的Rails已经生疏了,我也在创建一个点对象方面遇到了麻烦...如果我找到解决方案,我会再次在这里发布...我尝试了一些类似于下面答案的解决方案,但是目前还没有找到可行的方法。 - dave
2个回答

1
使用 st_point 作为类型,而不是 point
add_column :monuments, :grid_ref, :st_point, geographic: true

Postgresql添加了一个point类型,因此在postgis适配器中,类型名称被更改为st_point。详见https://github.com/rgeo/activerecord-postgis-adapter#point-and-polygon-types-with-activerecord-42

在3版本之前,支持点和多边形类型。在ActiveRecord 4.2中,Postgresql适配器添加了对本机Postgresql点和多边形类型的支持,这与该适配器具有相同名称的类型冲突。必须将PostGIS点类型引用为st_point,将PostGIS多边形类型引用为st_polygon。


1

找到了解决方案。必须指定SRID,地理工厂现在是球形工厂,并且该点是在指定SRID的球形工厂上调用的方法。

目前,我已经实现了以下辅助方法,它可以与rails 4.2.6、postgis和postgresql一起使用。

请注意,工厂首先需要经度参数 :)

def set_latlon(lat, lng)

  factory = RGeo::Geographic.spherical_factory(srid: 4326)

  # NOTE: this method takes the LNG parameter first!
  self.latlon = factory.point(lng, lat)

end

如果您正在遵循与我相同的空间配置教程,那么您将注意到以这种方式创建的行将失败。我通过将:point列替换为:geographic列来解决了这个问题。迁移代码如下。

class Location < ActiveRecord::Migration
  def change
    remove_column :locations, :latlon # formerly of type :point
    add_column :locations, :latlon, :geography, limit: {:srid=>4326, :type=>"point", :geographic=>true}, null: false
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接