为RGeo-ActiveRecord列指定点类型

时间:2016-02-16 09:23:52

标签: ruby-on-rails activerecord postgis rgeo

Address模型具有RGeo属性时,存在典型模式:

t.st_point :coordinates,   geographic: true, srid: 4326

通常它包含在RGeo::Geographic::SphericalPointImpl

Realty.last.address.coordinates
#<RGeo::Geographic::SphericalPointImpl:0x2b1a364b429c "POINT (106.5 10.5)">

但在某些情况下,它会被完全不合适的笛卡尔包装RGeo::Cartesian::PointImpl

包裹
Realty.joins(:address).select('realties.id, addresses.coordinates::geometry').first.coordinates
#<RGeo::Cartesian::PointImpl:0x2b1a364a691c "POINT (106.0 10.0)">

我使用'activerecord-postgis-adapter 3.1.4'rails 4.2.4

进行了最新的coordinates

也许有人知道如何解决这个问题,即让RGeo::Geographic::SphericalPointImpl始终返回function filter(array $array) { $filteredArray = array(); $allowedKeys = array('id', 'name', 'children'); foreach($array as $index => $element) { $filteredArray[$index] = array(); foreach ($element as $key => $value) { if(is_array($value) && in_array($key, $allowedKeys)) { $filteredArray[$index][$key] = filter($value); } else { if(in_array($key, $allowedKeys)) { $filteredArray[$index][$key] = $value; } } } } return $filteredArray; } 的实例?

1 个答案:

答案 0 :(得分:2)

当您选择addresses.coordinates::geometry列时,您强制Postgres返回几何类型的列。执行Realty.last.address.coordinates时,将返回不同的SQL类型(一个点)。

我会从您的SQL查询中删除::geometry

来自https://github.com/rgeo/rgeo-activerecord#spatial-factories-for-columns的文档:

activerecord-postgis-adapter使用SpatialFactoryStore类作为查找类型的注册表,将SQL类型转换为ruby类型。

SpatialFactoryStore单例类中注册空间工厂。 ActiveRecord模型中的每种空间类型都将使用SpatialFactoryStore来检索与其类型属性匹配的工厂。例如,您可以为点类型或与特定SRID匹配的类型或具有Z坐标或任何属性组合的类型设置不同的空间工厂。

此处列出了注册空间类型时支持的键及其默认值和其他允许值:

geo_type: "geometry", # point, polygon, line_string, geometry_collection, 
                      # multi_line_string, multi_point, multi_polygon
has_m:    false,      # true
has_z:    false,      # true
sql_type: "geometry", # geography
srid:     0,          # (any valid SRID)

对于地理类型,默认工厂为RGeo::Geographic.spherical_factory,对于几何类型,默认工厂为RGeo::Cartesian.preferred_factory

以下是一个示例设置:

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