mongoid/mongoid-geospatial

External (Geom) Libs

nofxx opened this issue · 8 comments

Came to two approaches:

Have Mongoid::Geospatial own Point, Polygon and LineString classes

pro: avoids cpu waste, no ifs to check which lib, and in MongoDB supported criteria for instance you won't be instantiating a RGeo or GeoRuby object just to make it an array again later.

Use a separate method to get the external lib object (#to_geo)

pro: same as the above, no ifs, everywhere it's not needed no cycles are wasted.

Solution for now:

Need to require "mongoid_geospatial_(rgeo or georuby)"

cons: single file to hold it all? another approach?

Not sure what you mean by "have Mongoid::Geospatial OWN Point, Polygon and LineString classes". What does own signify this context?

Need to

require "mongoid_geospatial/rgeo" or "mongoid_geospatial/georuby"

Aha, so the user can choose to use either lib, by simply including one of them. I think it is best to have both extensions included, then the user should include either of those libs before including mongoid_geospatial. Then mongoid_geospatial can determine which extension to include based on a define?(RGeo) check. (RGeo could be default if both are defined or should it include both extensions?).

With our classes we follow the unix principle, do just one thing (hopefully well).
This lib won't do anything mongodb doesn't. And it currently just do points and queries.
All the calculations, geom helpers, etc are delegated to some geo gem.

I like that way, the const_defined?(:RGeo), but would ppl consider it a caveat?
Need to always make sure the geo lib is loaded first.

Sounds good to me. Hollywood principle?

As I see it, even if you forget to load the specific Geo lib first, you can still manually include the necessary Geo lib extension when all your libs are loaded ;) It is just a convenience, in case you "do it right" and follow the "conventions".

But where can we load the extensions of the ext lib?
Remember, no 'ifs' on the #to_map method...

I've only now been looking at all your recent commits. I like your general ideas, however I'm not a fan of the :require on the gem statement in the Gemfile, in order to load the right Geo lib extensions.

I would go for either of the following design patterns:

# mongoid_geospatial

require 'mongoid_geospatial/geolibs/rgeo' if defined?(RGeo)
require 'mongoid_geospatial/geolibs/geo_ruby' if defined?(GeoRuby)

Not sure what to do in case both are defined. Alternatively always enforce that one has precedence over the other

# mongoid_geospatial

if defined?(RGeo)
  require 'mongoid_geospatial/geolibs/rgeo' 
elsif defined?(GeoRuby)
  require 'mongoid_geospatial/geolibs/geo_ruby'
end

Now we can just do:

# Gemfile

gem 'rgeo'
gem 'mongoid_geospatial'

And it will just work!

another approach that is more flexible is using a Configuration object via an initializer, similar to fx how Devise configures which ORM to use for authentication.

# initializers/mongoid_geospatial,rb

MongoidGeospation.config do |c|
  c.geolib :rgeo # will require the rgeo extension
end

This way, even if more than one Geo lib is loaded, you can still configure which one you want to use from within the project, perhaps based on other project specific factors you can't access from your Gemfile.

Taking the best of each approach, we could still use the optional :require as follows

# auto-magically determine which geo lib to require!
gem 'mongoid_geospatial', require: 'mongoid_geospatial_auto'

# or use "manual" configuration (default)
gem 'mongoid_geospatial'

I'm surprised all the mongoid specific geo functionality has disappeared. Is this now all handled by the geo libs such as RGeo et. al? To me, from reading the docs, it seems they still only have geo adapters for Active Record?

But hey, the less code and complexity the better ;)

Hello kristian!
Yea, the require is lenghty! Going to try the block config way. Makes it less magical.

Man, the only calculation this gem did was 10 lines for distance and spheroid_distance (haversine). All that code removed Moped does now. near, geoNear, within...etc. It was a stone in this project's shoe... rewrite mongoid is fail. We are an extension, not a pull commit ;)

@kristianmandrup check out the readme ;)
Think this one is good.
Also, please check out #7 , last missing method is Class#near.

You might also be interested in the following gems. The idea was originally mainly to introduce a more convenient API for doing geo operations, such as vector additions or fx generating a random point within a circle or box radius around another point etc.

https://github.com/kristianmandrup/geo_point
https://github.com/kristianmandrup/geo_vectors
https://github.com/kristianmandrup/geo-distance
https://github.com/kristianmandrup/geo_shapes

I think geo_point and geo_vectors are still pretty nice. I'm sure that geo_shapes however could take advantage of the built in functionality of RGeo fx. What do you think?