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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +49 -0
  4. data/.travis.yml +19 -0
  5. data/Gemfile +30 -0
  6. data/Guardfile +16 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +519 -0
  9. data/Rakefile +17 -0
  10. data/lib/mongoid/geospatial.rb +106 -0
  11. data/lib/mongoid/geospatial/ext/rgeo_spherical_point_impl.rb +18 -0
  12. data/lib/mongoid/geospatial/fields/box.rb +6 -0
  13. data/lib/mongoid/geospatial/fields/circle.rb +18 -0
  14. data/lib/mongoid/geospatial/fields/geometry_field.rb +41 -0
  15. data/lib/mongoid/geospatial/fields/line.rb +6 -0
  16. data/lib/mongoid/geospatial/fields/point.rb +143 -0
  17. data/lib/mongoid/geospatial/fields/polygon.rb +6 -0
  18. data/lib/mongoid/geospatial/helpers/delegate.rb +30 -0
  19. data/lib/mongoid/geospatial/helpers/spatial.rb +19 -0
  20. data/lib/mongoid/geospatial/helpers/sphere.rb +18 -0
  21. data/lib/mongoid/geospatial/version.rb +6 -0
  22. data/lib/mongoid/geospatial/wrappers/georuby.rb +33 -0
  23. data/lib/mongoid/geospatial/wrappers/rgeo.rb +43 -0
  24. data/mongoid-geospatial.gemspec +22 -0
  25. data/spec/models/address.rb +69 -0
  26. data/spec/models/alarm.rb +12 -0
  27. data/spec/models/bar.rb +13 -0
  28. data/spec/models/bus.rb +12 -0
  29. data/spec/models/event.rb +17 -0
  30. data/spec/models/farm.rb +13 -0
  31. data/spec/models/person.rb +97 -0
  32. data/spec/models/phone.rb +8 -0
  33. data/spec/models/place.rb +13 -0
  34. data/spec/models/river.rb +22 -0
  35. data/spec/mongoid/geospatial/fields/box_spec.rb +10 -0
  36. data/spec/mongoid/geospatial/fields/circle_spec.rb +10 -0
  37. data/spec/mongoid/geospatial/fields/line_spec.rb +40 -0
  38. data/spec/mongoid/geospatial/fields/point_spec.rb +254 -0
  39. data/spec/mongoid/geospatial/fields/polygon_spec.rb +84 -0
  40. data/spec/mongoid/geospatial/geospatial_spec.rb +143 -0
  41. data/spec/mongoid/geospatial/helpers/core_spec.rb +27 -0
  42. data/spec/mongoid/geospatial/helpers/delegate_spec.rb +54 -0
  43. data/spec/mongoid/geospatial/helpers/spatial_spec.rb +36 -0
  44. data/spec/mongoid/geospatial/helpers/sphere_spec.rb +26 -0
  45. data/spec/mongoid/geospatial/wrappers/georuby_spec.rb +66 -0
  46. data/spec/mongoid/geospatial/wrappers/rgeo_spec.rb +121 -0
  47. data/spec/spec_helper.rb +64 -0
  48. data/spec/support/authentication.rb +29 -0
  49. data/spec/support/mongod.conf +3 -0
  50. data/spec/support/mongoid.yml +19 -0
  51. 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
@@ -0,0 +1,12 @@
1
+ # Sample spec class
2
+ class Alarm
3
+ include Mongoid::Document
4
+ include Mongoid::Geospatial
5
+
6
+ field :name
7
+ field :radius, type: Circle
8
+ field :area, type: Box
9
+ field :spot, type: Point, sphere: true
10
+
11
+ spatial_scope :spot
12
+ end
@@ -0,0 +1,13 @@
1
+ # Sample spec class
2
+ class Bar
3
+ include Mongoid::Document
4
+ include Mongoid::Geospatial
5
+
6
+ field :name, type: String
7
+
8
+ geo_field :location
9
+
10
+ has_one :rating, as: :ratable
11
+
12
+ spatial_scope :location
13
+ end
@@ -0,0 +1,12 @@
1
+ # Sample spec class
2
+ class Bus
3
+ include Mongoid::Document
4
+ include Mongoid::Geospatial
5
+
6
+ field :name
7
+ field :plates, type: String
8
+ field :location, type: Point, delegate: true
9
+
10
+ spatial_index :location
11
+ spatial_scope :location
12
+ end
@@ -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
@@ -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,8 @@
1
+ # Sample spec class
2
+ class Phone
3
+ include Mongoid::Document
4
+ field :number
5
+
6
+ embeds_one :country_code
7
+ embedded_in :person
8
+ 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,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial::Box do
4
+
5
+ it 'should work' do
6
+ alarm = Alarm.new(area: [[1, 2], [3, 4]])
7
+ expect(alarm.area).to be_a Mongoid::Geospatial::Box
8
+ end
9
+
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial::Circle do
4
+
5
+ it 'should work' do
6
+ alarm = Alarm.new(radius: [[1, 2], 3])
7
+ expect(alarm.radius).to be_a Mongoid::Geospatial::Circle
8
+ end
9
+
10
+ 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