mongoid-geospatial 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|