将ActiveRecord列转换为PostGIS Point

时间:2013-02-27 16:57:19

标签: ruby-on-rails postgresql activerecord postgis rgeo

我的设置:

  • Ruby 2.0.0
  • Rails 3.2.12
  • 最近的pg gem
  • 最近的activerecord-postgis-adapter gem
  • 最近的rgeo-geojson gem
  • Postgres 9.1.6
  • PostGIS 2
我几天前问过类似的事情。 (Need to convert a Boolean from Postgres (== String) to a Ruby Boolean)。我必须将自定义选择中的值转换为布尔值。这很简单,只需将其添加到我的模型中:

def value_name
  ActiveRecord::ConnectionAdapters::Column.value_to_boolean(self[:value_name])
end

但现在我收到类型为Point的值(来自PostGIS的类型)。它在数据库中的字符串表示看起来像"0101000000EE7C3F355EF24F4019390B7BDA011940",但它必须成为(我认为)RGeo::Feature::PointRGeo::Geos::CAPIPointImpl?!

现在我查看了ActiveRecord::ConnectionAdapters::Columnhttp://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/Column),我只能找到value_to_booleanvalue_to_decimal

然后我认识到还有ActiveRecord::ConnectionAdapters::PostgreSQLColumnhttp://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/PostgreSQLColumn),但它似乎没有任何有用的方法。

谢谢!

3 个答案:

答案 0 :(得分:2)

尝试类似的东西:

def value_name
  point_regex = /POINT \(([0-9]*\.[0-9]*) ([0-9]*\.[0-9]*)\)/
  match_data = self[:value_name].match(point_regex)
  match_data[1], match_data[2]
end

它会返回几个代表你的观点的值[x,y]。 你必须做反过来,即定义一个value_name =(x,y)。

答案 1 :(得分:2)

我找到了一个解决方案(搜索了rgeoparse):

def my_value
  a = RGeo::WKRep::WKBParser.new
  a.parse(self[:my_value])
end

我只需要知道它是否正确。来自Java世界,我这样读了:

  • 对于每个(!)my_value:创建一个新的WKBParser实例

如果是这样的话:我怎样才能创建它的一个实例并在每次调用该方法时重用它?


或者更详细:自动解析器如何处理这个?它被称为何处?

我认为它是在这里创建的:https://github.com/dazuma/activerecord-postgis-adapter/blob/master/lib/active_record/connection_adapters/postgis_adapter/spatial_column.rb(第179和181行)

但是如何在我的模型中重复使用它?

背景信息:解析器会自动适用于真实的表列,但我的列会在查询中创建。


找到正确的方法:

def my_value
  RGeo::Geos.factory.parse_wkb(self[:my_value])
end

:)

答案 2 :(得分:2)

是的,postgis适配器确实有效,并提供更优雅的解决方案。

在我的Gemfile中:

gem 'rails', '3.2.12'

gem 'pg'
gem 'rgeo-activerecord'
gem 'activerecord-postgis-adapter'

然后在模型中:

class MyPoint < ActiveRecord::Base
  set_rgeo_factory_for_column(:geom, RGeo::Geos.factory(srid: 4326))
  attr_accessible :geom
end

查找RGeo安装是否支持Geos:

>> RGeo::Geos::supported?
true

这就是你得到的 - 模型的属性geom,在这种情况下RGeo::Geos::CAPIPointImpl(将根据工厂类别而变化)。要使此工厂正常工作,您需要在安装RGeo之前安装具有开发文件的Geos。不必是Geos工厂和4326,RGeo的工厂用纯Ruby实现,在文档中找到最匹配的工厂类和SRID:http://rubydoc.info/github/dazuma/rgeo/master/index