Pregunta

My setup:

  • Ruby 2.0.0
  • Rails 3.2.12
  • most recent pg gem
  • most recent activerecord-postgis-adapter gem
  • most recent rgeo-geojson gem
  • Postgres 9.1.6
  • PostGIS 2

I've asked something similar a few days ago. (Need to convert a Boolean from Postgres (== String) to a Ruby Boolean). There I had to convert a value from a custom select to boolean. This was pretty straight forward, by just adding this to my model:

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

But now I receive a value of type Point (which is a type from PostGIS). Its string representation in database looks like "0101000000EE7C3F355EF24F4019390B7BDA011940", but it has to become a (I think) RGeo::Feature::Point or maybe RGeo::Geos::CAPIPointImpl ?!

Now I looked at ActiveRecord::ConnectionAdapters::Column (http://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/Column), I can only find value_to_boolean and value_to_decimal.

Then I recognized that there is also ActiveRecord::ConnectionAdapters::PostgreSQLColumn (http://rubydoc.info/docs/rails/ActiveRecord/ConnectionAdapters/PostgreSQLColumn), but it doesn't seem to have any useful methods.

Thank you!

¿Fue útil?

Solución 2

I found a solution (searched for rgeo and parse):

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

I just need to know if it's the right way. Coming from the Java world, I read it like this:

  • For every(!) my_value: Create a new instance of WKBParser

If that's the case: How can I create just one instance of it and reuse it every time the method is called?


Or in more detail: How does the automatic parser handle this? Where does it get called?

I think it get's created here: https://github.com/dazuma/activerecord-postgis-adapter/blob/master/lib/active_record/connection_adapters/postgis_adapter/spatial_column.rb (Line 179 and 181)

But how can I reuse this in my model?

Background information: The parser automatically works for real table columns, but my column gets created within the query.


Found the right way:

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

:)

Otros consejos

Try something like that :

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

It will return a couple of value [x, y] representing your point. You have to do the inverse, i.e. define a value_name=(x,y).

Yep, postgis adapter really works, and provides much more elegant solution.

In my Gemfile:

gem 'rails', '3.2.12'

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

then in the model:

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

to find if Geos is supported in your RGeo installation:

>> RGeo::Geos::supported?
true

And that's what you get - model's attribute geom which is in this case RGeo::Geos::CAPIPointImpl (will vary depending on factory class). To get this factory working you need to have Geos with development files installed before installing RGeo. Doesn't have to be Geos factory and 4326, RGeo has factories implemented in pure Ruby, find your best match factory class and SRID in the docs: http://rubydoc.info/github/dazuma/rgeo/master/index

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top