【问题标题】:Convert an ActiveRecord column to PostGIS Point将 ActiveRecord 列转换为 PostGIS 点
【发布时间】:2013-02-27 16:57:18
【问题描述】:

我的设置:

  • Ruby 2.0.0
  • Rails 3.2.12
  • 最近的pg gem
  • 最近的activerecord-postgis-adapter gem
  • 最近的rgeo-geojson gem
  • Postgres 9.1.6
  • 后GIS 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::Point 或者可能是 RGeo::Geos::CAPIPointImpl ?!

现在看ActiveRecord::ConnectionAdapters::Column(http://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/Column),只能找到value_to_booleanvalue_to_decimal

然后我发现还有ActiveRecord::ConnectionAdapters::PostgreSQLColumn(http://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/PostgreSQLColumn),但是好像没有什么有用的方法。

谢谢!

【问题讨论】:

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


    【解决方案1】:

    尝试类似的方法:

    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)。

    【讨论】:

    • 这给了我一个错误:syntax error, unexpected '\n', expecting '='。也许是我的错。格式不一样。它是:"0101000000EE7C3F355EF24F4019390B7BDA011940"。我将编辑我的问题。
    • 这一次,我不知道你的字符串代表什么......我的解决方案只有在你有一个像“POINT(xx.xxx xx.xxx)”这样的字符串时才有效。
    • 我有一个解决方案,我会在几分钟后发布。它有效,但我不确定这是否是最好的方法......
    【解决方案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
    

    :)

    【讨论】:

      【解决方案3】:

      是的,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

      【讨论】:

        猜你喜欢
        • 2020-07-30
        • 2014-04-29
        • 2013-10-03
        • 2012-03-25
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-13
        相关资源
        最近更新 更多