rgeo / activerecord-mysql2spatial-adapter

ActiveRecord connection adapter for MySQL Spatial Extensions, based on mysql2 and rgeo
48 stars 64 forks source link

Specifying spatial types in test fixtures #2

Closed haxney closed 7 years ago

haxney commented 13 years ago

Having looked at the documentation and code for a bit, I can't figure out a way to specify geometry types in Rails YAML fixtures. Is there a way to do this, either by specifying the attributes directly with something like

model:
  pos: !ruby/object:Point
    x: 1
    y: 1

or by using WKT like this:

model:
  pos: POINT(1 1)

If there isn't already a way to do this, consider this a feature request for such functionality. I would be willing to help write the necessary code if given some pointers.

dazuma commented 13 years ago

Okay, I'm going to have to think about how to do fixtures properly. In general, YAML serialization is fairly high on the to-do list right now.

I see that you also have a fixture-related issue open with spatial_adapter. Since you've clearly spent some time trying to figure out spatial fixtures, would you say spatial_adapter's syntax for geometry objects within a fixture is the way to go, or do you think a syntax closer to your WKT example would be preferable?

haxney commented 13 years ago

would you say spatial_adapter's syntax for geometry objects within a fixture is the way to go, or do you think a syntax closer to your WKT example would be preferable?

I think the spatial_adapter-style syntax would be better, especially for more complex geometries, like polygon. WKT is nice for points, but the YAML syntax for points can be as short as:

model:
  pos: !ruby/object:Point {x: 1, y: 2}

Which negates most of the advantages of using WKT.

In order for YAML to create Point objects, rather than hashes, you'll need to use YAML::add_domain_type or add_ruby_type to register a handler. I was able to get the WKT version semi-working using the following (in my spec_helper.rb):

YAML.add_domain_type("haxney.org,2011","point") { |type, val| RGeo::Geographic.simple_mercator_factory.parse_wkt(val) }

and then using it in a YAML file like so:

model:
   pos: !haxney.org,2011/point POINT(5 -5)

This works, but it doesn't seem like an ideal solution. One issue that didn't have a clear solution was the handling of factories. It seems like having a factory for each geometry type is inherent in the structure of RGeo, and so it wouldn't make sense to create a point (or other geometry) without a factory.

One solution is to take advantage of the fact that the second argument to YAML::add_domain_type ("point" in my example) can be a regex, and the type block argument contains whatever the user provides. This would allow for something like:

model:
  pos: !haxney.org,2011/simple_mercator:point POINT(5 -5)

where the value of type would be "simple_mercator:point", and the block passed to YAML::add_domain_type could use that to create a point with a simple mercator factory. If you wanted to get really fancy, you could try to have some way of cramming arbitrary Proj4 projection definitions in there, but just having a few static options (like simple_mercator, spherical, cartesian, etc.) would be enough to get by. Alternatively, you could have the factory be an attribute like:

model:
  pos: !ruby/object:Point
    x: 5
    y: -5
    factory: simple_mercator

which would make putting arbitrary projection information much cleaner.

tetsutan commented 13 years ago

Hi. I have known this bug, too. So, I wrote a patch to read WKT (but not enough). Is this not right way to fix the problem? (I have checked Point as WKT only)

https://gist.github.com/1093641

januszm commented 7 years ago

@haxney @tetsutan is this still an issue or should we close it?

tetsutan commented 7 years ago

No problem. Thanks.