mongoid/mongoid-geospatial

View on GitHub
lib/mongoid/geospatial.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'mongoid'
# require 'active_support/core_ext/string/inflections'
# require 'active_support/concern'
require 'mongoid/geospatial/helpers/spatial'
require 'mongoid/geospatial/helpers/sphere'
require 'mongoid/geospatial/helpers/delegate'

module Mongoid
  #
  # Main Geospatial module
  #
  # include Mongoid::Geospatial
  #
  module Geospatial
    autoload :GeometryField, 'mongoid/geospatial/geometry_field'

    autoload :Point,         'mongoid/geospatial/fields/point'
    autoload :LineString,    'mongoid/geospatial/fields/line_string'
    autoload :Polygon,       'mongoid/geospatial/fields/polygon'

    autoload :Box,           'mongoid/geospatial/fields/box'
    autoload :Circle,        'mongoid/geospatial/fields/circle'

    autoload :VERSION,       'mongoid/geospatial/version'

    extend ActiveSupport::Concern

    # Symbols accepted as 'longitude', 'x'...
    LNG_SYMBOLS = [:x, :lon, :long, :lng, :longitude,
                   'x', 'lon', 'long', 'lng', 'longitude'].freeze

    # Symbols accepted as 'latitude', 'y'...
    LAT_SYMBOLS = [:y, :lat, :latitude, 'y', 'lat', 'latitude'].freeze

    # For distance spherical calculations
    EARTH_RADIUS_KM = 6371 # taken directly from mongodb
    RAD_PER_DEG = Math::PI / 180

    # Earth radius in multiple units
    EARTH_RADIUS = {
      m: EARTH_RADIUS_KM * 1000,
      km: EARTH_RADIUS_KM,
      mi: EARTH_RADIUS_KM * 0.621371192,
      ft: EARTH_RADIUS_KM * 5280 * 0.621371192,
      sm: EARTH_RADIUS_KM * 0.53995680345572 # sea mile
    }.freeze

    mattr_accessor :lng_symbols
    mattr_accessor :lat_symbols
    mattr_accessor :earth_radius
    mattr_accessor :factory

    @@lng_symbols  = LNG_SYMBOLS.dup
    @@lat_symbols  = LAT_SYMBOLS.dup
    @@earth_radius = EARTH_RADIUS.dup

    included do
      # attr_accessor :geo
      cattr_accessor :spatial_fields, :spatial_fields_indexed
      self.spatial_fields = []
      self.spatial_fields_indexed = []
    end

    def self.with_rgeo!
      require 'mongoid/geospatial/wrappers/rgeo'
    end

    def self.with_georuby!
      require 'mongoid/geospatial/wrappers/georuby'
    end

    # Methods applied to Document's class
    module ClassMethods
      #
      # Create Spatial index for given field
      #
      #
      # @param [String,Symbol] name
      # @param [Hash] options options for spatial_index
      #
      # http://www.mongodb.org/display/DOCS/Geospatial+Indexing
      # #GeospatialIndexing-geoNearCommand
      #
      def spatial_index(name, options = {})
        spatial_fields_indexed << name
        index({ name => '2d' }, options)
      end

      #
      # Creates Sphere index for given field
      #
      #
      # @param [String,Symbol] name
      # @param [Hash] options options for spatial_index
      #
      # http://www.mongodb.org/display/DOCS/Geospatial+Indexing
      # #GeospatialIndexing-geoNearCommand
      def sphere_index(name, options = {})
        spatial_fields_indexed << name
        index({ name => '2dsphere' }, options)
      end

      #
      # Creates Sphere index for given field
      #
      #
      # @param [String,Symbol] name
      # @param [Hash] options options for spatial_index
      #
      # http://www.mongodb.org/display/DOCS/Geospatial+Indexing
      # #GeospatialIndexing-geoNearCommand
      def spatial_scope(field, _opts = {})
        singleton_class.class_eval do
          # define_method(:close) do |args|
          define_method(:nearby) do |args|
            queryable.where(field.near_sphere => args)
          end
        end
      end
    end
  end
end

require 'mongoid/geospatial/config'