mongoid-geospatial 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +49 -0
- data/.travis.yml +19 -0
- data/Gemfile +30 -0
- data/Guardfile +16 -0
- data/MIT-LICENSE +20 -0
- data/README.md +519 -0
- data/Rakefile +17 -0
- data/lib/mongoid/geospatial.rb +106 -0
- data/lib/mongoid/geospatial/ext/rgeo_spherical_point_impl.rb +18 -0
- data/lib/mongoid/geospatial/fields/box.rb +6 -0
- data/lib/mongoid/geospatial/fields/circle.rb +18 -0
- data/lib/mongoid/geospatial/fields/geometry_field.rb +41 -0
- data/lib/mongoid/geospatial/fields/line.rb +6 -0
- data/lib/mongoid/geospatial/fields/point.rb +143 -0
- data/lib/mongoid/geospatial/fields/polygon.rb +6 -0
- data/lib/mongoid/geospatial/helpers/delegate.rb +30 -0
- data/lib/mongoid/geospatial/helpers/spatial.rb +19 -0
- data/lib/mongoid/geospatial/helpers/sphere.rb +18 -0
- data/lib/mongoid/geospatial/version.rb +6 -0
- data/lib/mongoid/geospatial/wrappers/georuby.rb +33 -0
- data/lib/mongoid/geospatial/wrappers/rgeo.rb +43 -0
- data/mongoid-geospatial.gemspec +22 -0
- data/spec/models/address.rb +69 -0
- data/spec/models/alarm.rb +12 -0
- data/spec/models/bar.rb +13 -0
- data/spec/models/bus.rb +12 -0
- data/spec/models/event.rb +17 -0
- data/spec/models/farm.rb +13 -0
- data/spec/models/person.rb +97 -0
- data/spec/models/phone.rb +8 -0
- data/spec/models/place.rb +13 -0
- data/spec/models/river.rb +22 -0
- data/spec/mongoid/geospatial/fields/box_spec.rb +10 -0
- data/spec/mongoid/geospatial/fields/circle_spec.rb +10 -0
- data/spec/mongoid/geospatial/fields/line_spec.rb +40 -0
- data/spec/mongoid/geospatial/fields/point_spec.rb +254 -0
- data/spec/mongoid/geospatial/fields/polygon_spec.rb +84 -0
- data/spec/mongoid/geospatial/geospatial_spec.rb +143 -0
- data/spec/mongoid/geospatial/helpers/core_spec.rb +27 -0
- data/spec/mongoid/geospatial/helpers/delegate_spec.rb +54 -0
- data/spec/mongoid/geospatial/helpers/spatial_spec.rb +36 -0
- data/spec/mongoid/geospatial/helpers/sphere_spec.rb +26 -0
- data/spec/mongoid/geospatial/wrappers/georuby_spec.rb +66 -0
- data/spec/mongoid/geospatial/wrappers/rgeo_spec.rb +121 -0
- data/spec/spec_helper.rb +64 -0
- data/spec/support/authentication.rb +29 -0
- data/spec/support/mongod.conf +3 -0
- data/spec/support/mongoid.yml +19 -0
- metadata +164 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'geo_ruby'
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Geospatial
|
5
|
+
# Wrapper to GeoRuby's Point
|
6
|
+
class Point
|
7
|
+
delegate :distance, to: :to_geo
|
8
|
+
|
9
|
+
def to_geo
|
10
|
+
return unless valid?
|
11
|
+
GeoRuby::SimpleFeatures::Point.xy(x, y)
|
12
|
+
end
|
13
|
+
|
14
|
+
def geo_distance(other)
|
15
|
+
to_geo.spherical_distance(other.to_geo)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Wrapper to GeoRuby's Line
|
20
|
+
class Line < GeometryField
|
21
|
+
def to_geo
|
22
|
+
GeoRuby::SimpleFeatures::LineString.from_coordinates(self)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Wrapper to GeoRuby's Polygon
|
27
|
+
class Polygon < GeometryField
|
28
|
+
def to_geo
|
29
|
+
GeoRuby::SimpleFeatures::Polygon.from_coordinates(self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rgeo'
|
2
|
+
require 'mongoid_geospatial/ext/rgeo_spherical_point_impl'
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Geospatial
|
6
|
+
# Wrapper to Rgeo's Point
|
7
|
+
class Point
|
8
|
+
def to_rgeo
|
9
|
+
RGeo::Geographic.spherical_factory.point x, y
|
10
|
+
end
|
11
|
+
|
12
|
+
def rgeo_distance(other)
|
13
|
+
to_rgeo.distance other.to_rgeo
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Rgeo's GeometryField concept
|
18
|
+
class GeometryField
|
19
|
+
private
|
20
|
+
|
21
|
+
def points
|
22
|
+
map do |pair|
|
23
|
+
RGeo::Geographic.spherical_factory.point(*pair)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Wrapper to Rgeo's Line
|
29
|
+
class Line < GeometryField
|
30
|
+
def to_rgeo
|
31
|
+
RGeo::Geographic.spherical_factory.line_string points
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Wrapper to Rgeo's Polygon
|
36
|
+
class Polygon < GeometryField
|
37
|
+
def to_rgeo
|
38
|
+
ring = RGeo::Geographic.spherical_factory.linear_ring points
|
39
|
+
RGeo::Geographic.spherical_factory.polygon ring
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/mongoid/geospatial/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ['Ryan Ong', 'Marcos Piccinini']
|
6
|
+
gem.email = ['use@git.hub.com']
|
7
|
+
gem.description = 'Mongoid Extension that simplifies MongoDB casting and operations on spatial Ruby objects.'
|
8
|
+
gem.summary = 'Mongoid Extension that simplifies MongoDB Geospatial Operations.'
|
9
|
+
gem.homepage = 'https://github.com/nofxx/mongoid-geospatial'
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = 'mongoid-geospatial'
|
15
|
+
gem.require_paths = ['lib']
|
16
|
+
gem.version = Mongoid::Geospatial::VERSION
|
17
|
+
gem.license = 'MIT'
|
18
|
+
|
19
|
+
gem.add_dependency('mongoid', ['>= 3.0.0'])
|
20
|
+
gem.add_dependency('activemodel', ['>= 3.2'])
|
21
|
+
gem.add_dependency('activesupport', ['>= 3.2'])
|
22
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class Address
|
3
|
+
include Mongoid::Document
|
4
|
+
|
5
|
+
field :_id, type: String, default: -> { street.try(:parameterize) }
|
6
|
+
|
7
|
+
attr_accessor :mode
|
8
|
+
|
9
|
+
field :address_type
|
10
|
+
field :number, type: Integer
|
11
|
+
field :street
|
12
|
+
field :city
|
13
|
+
field :state
|
14
|
+
field :post_code
|
15
|
+
field :parent_title
|
16
|
+
field :services, type: Array
|
17
|
+
field :latlng, type: Array
|
18
|
+
field :map, type: Hash
|
19
|
+
|
20
|
+
embeds_many :locations, validate: false
|
21
|
+
embeds_one :code, validate: false
|
22
|
+
embeds_one :target, as: :targetable, validate: false
|
23
|
+
|
24
|
+
embedded_in :addressable, polymorphic: true do
|
25
|
+
def extension
|
26
|
+
'Testing'
|
27
|
+
end
|
28
|
+
|
29
|
+
def doctor?
|
30
|
+
title == 'Dr'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
accepts_nested_attributes_for :locations, :code, :target
|
35
|
+
|
36
|
+
belongs_to :account
|
37
|
+
|
38
|
+
scope :without_postcode, where(postcode: nil)
|
39
|
+
scope :rodeo, where(street: 'Rodeo Dr') do
|
40
|
+
def mansion?
|
41
|
+
all? { |address| address.street == 'Rodeo Dr' }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
validates_presence_of :street, on: :update
|
46
|
+
validates_format_of :street, with: /\D/, allow_nil: true
|
47
|
+
|
48
|
+
def set_parent=(set = false)
|
49
|
+
self.parent_title = addressable.title if set
|
50
|
+
end
|
51
|
+
|
52
|
+
def <=>(other)
|
53
|
+
street <=> other.street
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def california
|
58
|
+
where(state: 'CA')
|
59
|
+
end
|
60
|
+
|
61
|
+
def homes
|
62
|
+
where(address_type: 'Home')
|
63
|
+
end
|
64
|
+
|
65
|
+
def streets
|
66
|
+
all.map(&:street)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/models/bar.rb
ADDED
data/spec/models/bus.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class Event
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Geospatial
|
5
|
+
|
6
|
+
field :name
|
7
|
+
field :date, type: Date
|
8
|
+
|
9
|
+
field :location, type: Point, delegate: true, default: [7, 7]
|
10
|
+
|
11
|
+
def self.each_day(start_date, end_date)
|
12
|
+
groups = only(:date).asc(:date).where(:date.gte => start_date, :date.lte => end_date).group
|
13
|
+
groups.each do |hash|
|
14
|
+
yield(hash['date'], hash['group'])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/models/farm.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class Farm
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Geospatial
|
5
|
+
|
6
|
+
field :name, type: String
|
7
|
+
field :geom, type: Point, spatial: true
|
8
|
+
field :area, type: Polygon, spatial: true
|
9
|
+
field :m2, type: Fixnum
|
10
|
+
|
11
|
+
spatial_index :geom
|
12
|
+
spatial_index :area
|
13
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class Person
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
# include Mongoid::Versioning
|
6
|
+
include Mongoid::Geospatial
|
7
|
+
|
8
|
+
attr_accessor :mode
|
9
|
+
|
10
|
+
class_attribute :somebody_elses_important_class_options
|
11
|
+
self.somebody_elses_important_class_options = { keep_me_around: true }
|
12
|
+
|
13
|
+
field :ssn
|
14
|
+
field :title
|
15
|
+
field :terms, type: Boolean
|
16
|
+
field :pets, type: Boolean, default: false
|
17
|
+
field :age, type: Integer, default: 100
|
18
|
+
field :dob, type: Date
|
19
|
+
field :lunch_time, type: Time
|
20
|
+
field :aliases, type: Array
|
21
|
+
field :map, type: Hash
|
22
|
+
field :score, type: Integer
|
23
|
+
field :owner_id, type: Integer
|
24
|
+
field :reading, type: Object
|
25
|
+
# field :bson_id, type: bson_object_id_class
|
26
|
+
field :employer_id
|
27
|
+
field :security_code
|
28
|
+
field :blood_alcohol_content, type: Float, default: -> { 0.0 }
|
29
|
+
field :last_drink_taken_at, type: Date, default: -> { 1.day.ago.in_time_zone('Alaska') }
|
30
|
+
|
31
|
+
# Geo
|
32
|
+
field :location, type: Point
|
33
|
+
|
34
|
+
index age: 1
|
35
|
+
index addresses: 1
|
36
|
+
index dob: 1
|
37
|
+
index name: 1
|
38
|
+
index title: 1
|
39
|
+
index({ ssn: 1 }, unique: true)
|
40
|
+
|
41
|
+
validates_format_of :ssn, without: /\$\$\$/
|
42
|
+
|
43
|
+
attr_reader :rescored
|
44
|
+
|
45
|
+
# attr_protected :security_code, :owner_id
|
46
|
+
|
47
|
+
embeds_many :addresses, as: :addressable do
|
48
|
+
def extension
|
49
|
+
'Testing'
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_by_street(street)
|
53
|
+
@target.select { |doc| doc.street == street }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
accepts_nested_attributes_for :addresses
|
58
|
+
|
59
|
+
scope :minor, -> { where(:age.lt => 18) }
|
60
|
+
scope :without_ssn, -> { without(:ssn) }
|
61
|
+
|
62
|
+
def score_with_rescoring=(score)
|
63
|
+
@rescored = score.to_i + 20
|
64
|
+
self.score_without_rescoring = score
|
65
|
+
end
|
66
|
+
|
67
|
+
alias_method_chain :score=, :rescoring
|
68
|
+
|
69
|
+
def update_addresses
|
70
|
+
addresses.each do |address|
|
71
|
+
address.street = 'Updated Address'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def employer=(emp)
|
76
|
+
self.employer_id = emp.id
|
77
|
+
end
|
78
|
+
|
79
|
+
class << self
|
80
|
+
def accepted
|
81
|
+
criteria.where(terms: true)
|
82
|
+
end
|
83
|
+
|
84
|
+
def knight
|
85
|
+
criteria.where(title: 'Sir')
|
86
|
+
end
|
87
|
+
|
88
|
+
def old
|
89
|
+
criteria.where(age: { '$gt' => 50 })
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Inheritance test
|
95
|
+
class Doctor < Person
|
96
|
+
field :specialty
|
97
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class Place
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Geospatial
|
5
|
+
|
6
|
+
field :name, type: String
|
7
|
+
field :location, type: Point, spatial: true
|
8
|
+
|
9
|
+
has_one :rating, as: :ratable
|
10
|
+
|
11
|
+
spatial_index :location
|
12
|
+
spatial_scope :location
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Sample spec class
|
2
|
+
class River
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Geospatial
|
5
|
+
|
6
|
+
field :name, type: String
|
7
|
+
field :length, type: Integer
|
8
|
+
field :discharge, type: Integer
|
9
|
+
field :course, type: Line, spatial: true
|
10
|
+
# set return_array to true if you do not want a hash returned all the time
|
11
|
+
field :source, type: Point, spatial: true
|
12
|
+
field :mouth, type: Point, spatial: { lat: 'latitude', lng: 'longitude' }
|
13
|
+
field :mouth_array, type: Array, spatial: { return_array: true }
|
14
|
+
|
15
|
+
# simplified spatial indexing
|
16
|
+
# you can only index one field in mongodb < 1.9
|
17
|
+
spatial_index :source
|
18
|
+
# alternatives
|
19
|
+
# index [[ :spatial, Mongo::GEO2D ]], {min:-400, max:400}
|
20
|
+
# index [[ :spatial, Mongo::GEO2D ]], {bit:32}
|
21
|
+
# index [[ :spatial, Mongo::GEO2D ],:name]
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::Geospatial::Line do
|
4
|
+
|
5
|
+
describe '(de)mongoize' do
|
6
|
+
|
7
|
+
it 'should support a field mapped as linestring' do
|
8
|
+
river = River.new(course: [[5, 5], [6, 5], [6, 6], [5, 6]])
|
9
|
+
expect(river.course).to be_a Mongoid::Geospatial::Line
|
10
|
+
expect(river.course).to eq([[5, 5], [6, 5], [6, 6], [5, 6]])
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should support a field mapped as linestring' do
|
14
|
+
River.create!(course: [[5, 5], [6, 5], [6, 6], [5, 6]])
|
15
|
+
expect(River.first.course).to eq([[5, 5], [6, 5], [6, 6], [5, 6]])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have a bounding box' do
|
19
|
+
geom = Mongoid::Geospatial::Line.new [[1, 5], [6, 5], [6, 6], [5, 6]]
|
20
|
+
expect(geom.bbox).to eq([[1, 5], [6, 6]])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have a center point' do
|
24
|
+
geom = Mongoid::Geospatial::Line.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
25
|
+
expect(geom.center).to eq([5.0, 5.0])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should have a radius helper' do
|
29
|
+
geom = Mongoid::Geospatial::Line.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
30
|
+
expect(geom.radius(10)).to eq([[5.0, 5.0], 10])
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should have a radius sphere' do
|
34
|
+
geom = Mongoid::Geospatial::Line.new [[1, 1], [1, 1], [9, 9], [9, 9]]
|
35
|
+
expect(geom.radius_sphere(10)[1]).to be_within(0.001).of(0.001569)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|