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,27 @@
1
+ module Mongoid
2
+ module Geospatial
3
+ def self.from_array(ary)
4
+ ary[0..1].map(&:to_f)
5
+ end
6
+
7
+ def self.from_hash(hsh)
8
+ fail 'Hash must have at least 2 items' if hsh.size < 2
9
+ [from_hash_x(hsh), from_hash_y(hsh)]
10
+ end
11
+
12
+ def self.from_hash_y(hsh)
13
+ v = (Mongoid::Geospatial.lat_symbols & hsh.keys).first
14
+ return hsh[v].to_f if !v.nil? && hsh[v]
15
+ fail "Hash must contain #{Mongoid::Geospatial.lat_symbols.inspect} if ruby version is less than 1.9" if RUBY_VERSION.to_f < 1.9
16
+ fail "Hash cannot contain #{Mongoid::Geospatial.lng_symbols.inspect} as the second item if there is no #{Mongoid::Geospatial.lat_symbols.inspect}" if Mongoid::Geospatial.lng_symbols.index(hsh.keys[1])
17
+ hsh.values[1].to_f
18
+ end
19
+
20
+ def self.from_hash_x(hsh)
21
+ v = (Mongoid::Geospatial.lng_symbols & hsh.keys).first
22
+ return hsh[v].to_f if !v.nil? && hsh[v]
23
+ fail "Hash cannot contain #{Mongoid::Geospatial.lat_symbols.inspect} as the first item if there is no #{Mongoid::Geospatial.lng_symbols.inspect}" if Mongoid::Geospatial.lat_symbols.index(keys[0])
24
+ values[0].to_f
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Fields do
4
+
5
+ context 'delegate' do
6
+
7
+ before do
8
+ Bus.create_indexes
9
+ end
10
+
11
+ context 'x, y helpers' do
12
+
13
+ let(:bus) { Bus.create!(name: 'Far', location: [7, 8]) }
14
+
15
+ it 'should set instance method x' do
16
+ expect(bus.x).to eq(7)
17
+ end
18
+
19
+ it 'should set instance method y' do
20
+ expect(bus.y).to eq(8)
21
+ end
22
+
23
+ it 'should set instance method x=' do
24
+ bus.x = 9
25
+ expect(bus.x).to eq(9)
26
+ end
27
+
28
+ it 'should set instance method y=' do
29
+ bus.y = 9
30
+ expect(bus.y).to eq(9)
31
+ end
32
+
33
+ end
34
+
35
+ it 'should set instance methods x= and y=' do
36
+ bus = Bus.create!(name: 'B', location: [7, 7])
37
+ bus.x = 9; bus.y = 9
38
+ expect(bus.location.to_a).to eq([9, 9])
39
+ end
40
+
41
+ it 'should work fine with default values' do
42
+ event = Event.create!(name: 'Bvent')
43
+ event.x = 9; event.y = 9
44
+ expect(event.location.to_a).to eq([9, 9])
45
+ end
46
+
47
+ it 'should not work fine with nils' do
48
+ bus = Bus.create!(name: 'B', location: nil)
49
+ expect { bus.x = 9; bus.y = 9 }.to raise_error(NoMethodError)
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Fields do
4
+
5
+ context 'spatial' do
6
+
7
+ before do
8
+ Bar.create_indexes
9
+ end
10
+
11
+ it 'should created indexes' do
12
+ expect(Bar.collection.indexes[location: '2d']).not_to be_nil
13
+ end
14
+
15
+ it 'should set spatial fields' do
16
+ expect(Bar.spatial_fields).to eql([:location])
17
+ end
18
+
19
+ it 'should set some class methods' do
20
+ far = Bar.create!(name: 'Far', location: [7, 7])
21
+ near = Bar.create!(name: 'Near', location: [2, 2])
22
+ expect(Bar.nearby([1, 1])).to eq([near, far])
23
+ end
24
+
25
+ # it "should set some class methods" do
26
+ # far = Bar.create!(name: "Far", location: [7,7])
27
+ # near = Bar.create!(name: "Near", location: [2,2])
28
+ # Bar.near_location([1,1]).should eq([near, far])
29
+ # end
30
+
31
+ end
32
+
33
+ context 'geom' do
34
+ end
35
+
36
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Fields do
4
+
5
+ context 'spatial' do
6
+
7
+ before do
8
+ Alarm.create_indexes
9
+ end
10
+
11
+ it 'should created indexes' do
12
+ expect(Alarm.collection.indexes[spot: '2dsphere']).not_to be_nil
13
+ end
14
+
15
+ it 'should set spatial fields' do
16
+ expect(Alarm.spatial_fields).to eql([:spot])
17
+ end
18
+
19
+ it 'should work fine indexed' do
20
+ far = Alarm.create!(name: 'Far', spot: [7, 7])
21
+ expect(far.spot).to be_instance_of(Mongoid::Geospatial::Point)
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial::Point do
4
+
5
+ it 'should not interfer with mongoid' do
6
+ Place.create!(name: "Moe's")
7
+ expect(Place.count).to eql(1)
8
+ end
9
+
10
+ it 'should not respond to distance before loading external gem' do
11
+ bar = Place.create!(location: [5, 5])
12
+ expect(bar.location).not_to respond_to(:distance)
13
+ end
14
+
15
+ describe 'queryable' do
16
+
17
+ before do
18
+ Mongoid::Geospatial.with_georuby!
19
+ Place.create_indexes
20
+ end
21
+
22
+ describe '(de)mongoize' do
23
+
24
+ it 'should mongoize array' do
25
+ geom = Place.new(location: [10, -9]).location
26
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
27
+ expect(geom.to_geo.class).to eql(GeoRuby::SimpleFeatures::Point)
28
+ expect(geom.x).to be_within(0.1).of(10)
29
+ expect(geom.to_geo.y).to be_within(0.1).of(-9)
30
+ end
31
+
32
+ it 'should mongoize hash' do
33
+ geom = Place.new(location: { x: 10, y: -9 }).location
34
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
35
+ expect(geom.to_geo.class).to eql(GeoRuby::SimpleFeatures::Point)
36
+ end
37
+
38
+ it 'should accept a GeoRuby point' do
39
+ point = GeoRuby::SimpleFeatures::Point.from_x_y 1, 2
40
+ bar = Place.create!(location: point)
41
+ expect(bar.location.x).to be_within(0.1).of(1)
42
+ expect(bar.location.y).to be_within(0.1).of(2)
43
+ end
44
+
45
+ it 'should calculate 3d distances by default' do
46
+ bar = Place.create! location: [-73.77694444, 40.63861111]
47
+ bar2 = Place.create! location: [-118.40, 33.94] # ,:unit=>:mi, :spherical => true)
48
+ expect(bar.location.geo_distance(bar2.location).to_i).to be_within(1).of(3_973_808)
49
+ end
50
+
51
+ describe 'simple features' do
52
+
53
+ it 'should mongoize lines' do
54
+ river = River.new(course: [[1, 2], [3, 4], [5, 6]])
55
+ expect(river.course.to_geo).to be_instance_of(GeoRuby::SimpleFeatures::LineString)
56
+ end
57
+
58
+ it 'should mongoize polygon' do
59
+ farm = Farm.new(area: [[1, 2], [3, 4], [5, 6]])
60
+ expect(farm.area.to_geo).to be_instance_of(GeoRuby::SimpleFeatures::Polygon)
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'RGeo Wrapper' do
4
+
5
+ before(:all) do
6
+ # Mongoid::Geospatial.send(:remove_const, 'Point')
7
+ # Mongoid::Geospatial.send(:remove_const, 'Polygon')
8
+ # Mongoid::Geospatial.send(:remove_const, 'Line')
9
+
10
+ # load "#{File.dirname(__FILE__)}/../../../lib/mongoid/geospatial/fields/point.rb"
11
+ # load "#{File.dirname(__FILE__)}/../../../lib/mongoid/geospatial/fields/polygon.rb"
12
+ # load "#{File.dirname(__FILE__)}/../../../lib/mongoid/geospatial/fields/line.rb"
13
+
14
+ # Object.send(:remove_const, 'Bar')
15
+ # load "#{File.dirname(__FILE__)}/../../models/bar.rb"
16
+
17
+ # Object.send(:remove_const, 'Farm')
18
+ # load "#{File.dirname(__FILE__)}/../../models/farm.rb"
19
+
20
+ # Object.send(:remove_const, 'River')
21
+ # load "#{File.dirname(__FILE__)}/../../models/river.rb"
22
+ end
23
+
24
+ describe Mongoid::Geospatial::Point do
25
+ it 'should not interfer with mongoid' do
26
+ Bar.create!(name: "Moe's")
27
+ expect(Bar.count).to eql(1)
28
+ end
29
+
30
+ it 'should not respond to distance before loading external' do
31
+ bar = Bar.create!(location: [5, 5])
32
+ expect(bar.location).not_to respond_to(:distance)
33
+ end
34
+ end
35
+
36
+ describe Mongoid::Geospatial::Polygon do
37
+ it 'should not interfer with mongoid' do
38
+ Farm.create!(name: 'Springfield Nuclear Power Plant')
39
+ expect(Farm.count).to eql(1)
40
+ end
41
+
42
+ it 'should not respond to to_geo before loading external' do
43
+ farm = Farm.create!(area: [[5, 5], [6, 5], [6, 6], [5, 6]])
44
+ expect(farm.area).not_to respond_to(:to_geo)
45
+ end
46
+ end
47
+
48
+ describe Mongoid::Geospatial::Line do
49
+ it 'should not interfer with mongoid' do
50
+ River.create!(name: 'Mississippi')
51
+ expect(River.count).to eql(1)
52
+ end
53
+
54
+ it 'should not respond to to_geo before loading external' do
55
+ river = River.create!(course: [[5, 5], [6, 5], [6, 6], [5, 6]])
56
+ expect(river.course).not_to respond_to(:to_geo)
57
+ end
58
+ end
59
+
60
+ describe 'queryable' do
61
+
62
+ before do
63
+ Mongoid::Geospatial.with_rgeo!
64
+ Bar.create_indexes
65
+ Farm.create_indexes
66
+ River.create_indexes
67
+ end
68
+
69
+ describe '(de)mongoize' do
70
+
71
+ describe Mongoid::Geospatial::Point do
72
+ it 'should mongoize array' do
73
+ geom = Bar.new(location: [10, -9]).location
74
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
75
+ expect(geom.to_rgeo.class).to eql(RGeo::Geographic::SphericalPointImpl)
76
+ expect(geom.x).to be_within(0.1).of(10)
77
+ expect(geom.to_rgeo.y).to be_within(0.1).of(-9)
78
+ end
79
+
80
+ it 'should mongoize hash' do
81
+ geom = Bar.new(location: { x: 10, y: -9 }).location
82
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
83
+ expect(geom.to_rgeo.class).to eql(RGeo::Geographic::SphericalPointImpl)
84
+ end
85
+
86
+ it 'should accept an RGeo object' do
87
+ point = RGeo::Geographic.spherical_factory.point 1, 2
88
+ bar = Bar.create!(location: point)
89
+ expect(bar.location.x).to be_within(0.1).of(1)
90
+ expect(bar.location.y).to be_within(0.1).of(2)
91
+ end
92
+
93
+ it 'should calculate 3d distances by default' do
94
+ bar = Bar.create! location: [-73.77694444, 40.63861111]
95
+ bar2 = Bar.create! location: [-118.40, 33.94] # ,:unit=>:mi, :spherical => true)
96
+ expect(bar.location.rgeo_distance(bar2.location).to_i).to be_within(1).of(3_978_262)
97
+ end
98
+ end
99
+
100
+ describe Mongoid::Geospatial::Polygon do
101
+ it 'should mongoize array' do
102
+ geom = Farm.create!(area: [[5, 5], [6, 5], [6, 6], [5, 6]]).area
103
+ expect(geom.class).to eql(Mongoid::Geospatial::Polygon)
104
+ expect(geom.to_rgeo.class).to eql(RGeo::Geographic::SphericalPolygonImpl)
105
+ expect(geom.to_rgeo.to_s)
106
+ .to eq 'POLYGON ((5.0 5.0, 6.0 5.0, 6.0 6.0, 5.0 6.0, 5.0 5.0))'
107
+ end
108
+ end
109
+
110
+ describe Mongoid::Geospatial::Line do
111
+ it 'should mongoize array' do
112
+ geom = River.create!(course: [[5, 5], [6, 5], [6, 6], [5, 6]]).course
113
+ expect(geom.class).to eql(Mongoid::Geospatial::Line)
114
+ expect(geom.to_rgeo.class).to eql(RGeo::Geographic::SphericalLineStringImpl)
115
+ expect(geom.to_rgeo.to_s)
116
+ .to eq 'LINESTRING (5.0 5.0, 6.0 5.0, 6.0 6.0, 5.0 6.0)'
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,64 @@
1
+ # require 'pry'
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+
5
+ MODELS = File.join(File.dirname(__FILE__), 'models')
6
+ SUPPORT = File.join(File.dirname(__FILE__), 'support')
7
+ $LOAD_PATH.unshift(MODELS)
8
+ $LOAD_PATH.unshift(SUPPORT)
9
+
10
+ if ENV['CI']
11
+ # require "simplecov"
12
+ require 'coveralls'
13
+ Coveralls.wear!
14
+ # SimpleCov.formatter = Coveralls::SimpleCov::Formatter
15
+ # SimpleCov.start do
16
+ # add_filter "spec"
17
+ # end
18
+ end
19
+
20
+ require 'mongoid'
21
+ # require "mocha"
22
+ require 'rspec'
23
+ require 'mongoid/geospatial'
24
+
25
+ # These environment variables can be set if wanting to test against a database
26
+ # that is not on the local machine.
27
+ ENV['MONGOID_SPEC_HOST'] ||= 'localhost'
28
+ ENV['MONGOID_SPEC_PORT'] ||= '27018'
29
+
30
+ # These are used when creating any connection in the test suite.
31
+ HOST = ENV['MONGOID_SPEC_HOST']
32
+ PORT = ENV['MONGOID_SPEC_PORT'].to_i
33
+
34
+ LOGGER = Logger.new($stdout)
35
+
36
+ if RUBY_VERSION >= '1.9.2'
37
+ YAML::ENGINE.yamler = 'syck'
38
+ end
39
+
40
+ puts "Running with Mongoid v#{Mongoid::VERSION}"
41
+
42
+ Mongoid.configure do |config|
43
+ config.connect_to('mongoid_geo_test')
44
+ end
45
+
46
+ # Autoload every model for the test suite that sits in spec/app/models.
47
+ Dir[File.join(MODELS, '*.rb')].sort.each do |file|
48
+ name = File.basename(file, '.rb')
49
+ autoload name.camelize.to_sym, name
50
+ end
51
+
52
+ Dir[File.join(SUPPORT, '*.rb')].each { |file| require File.basename(file) }
53
+
54
+ def bson_object_id_class
55
+ Moped::BSON::ObjectId
56
+ end
57
+
58
+ RSpec.configure do |config|
59
+ # config.mock_with(:mocha)
60
+
61
+ config.before(:each) do
62
+ Mongoid.purge!
63
+ end
64
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module Support #:nodoc:
3
+ # module Authentication
4
+ # extend self
5
+
6
+ # def configured?
7
+ # begin
8
+ # master_uri = "mongodb://mongoid:test@localhost:27017/mongoid_geospatial_test"
9
+ # Mongo::Connection.from_uri(master_uri)
10
+ # true
11
+ # rescue Mongo::AuthenticationError => e
12
+ # false
13
+ # end
14
+ # end
15
+
16
+ # def message
17
+ # %Q{
18
+ # ---------------------------------------------------------------------
19
+ # A user needs to be configured for authentication, otherwise some
20
+ # configuration specs will not get run. You may set it up from the
21
+ # mongo console:
22
+
23
+ # $ use mongoid_geospatial_test;
24
+ # $ db.addUser("mongoid", "test");
25
+ # ---------------------------------------------------------------------
26
+ # }
27
+ # end
28
+ # end
29
+ end
@@ -0,0 +1,3 @@
1
+ dbpath = /usr/local/var/mongodb
2
+ master = true
3
+ bind_ip = 127.0.0.1
@@ -0,0 +1,19 @@
1
+ test:
2
+ database: mongoid_geospatial_test
3
+ host: localhost
4
+ port: 27018
5
+ slaves:
6
+ # - host: localhost
7
+ # port: 27018
8
+ # - host: localhost
9
+ # port: 27019
10
+ # allow_dynamic_fields: false
11
+ # include_root_in_json: true
12
+ # parameterize_keys: false
13
+ # persist_in_safe_mode: false
14
+ # raise_not_found_error: false
15
+ # reconnect_time: 5
16
+ # autocreate_indexes: false
17
+ # persist_types: false
18
+ # option_no_exist: false
19
+ # skip_version_check: false