mongoid-geospatial 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
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,254 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial::Point do
4
+
5
+ it 'should not interfer with mongoid' do
6
+ Bar.create!(name: "Moe's")
7
+ expect(Bar.count).to eql(1)
8
+ end
9
+
10
+ it 'should not fail if point is nil' do
11
+ bar = Bar.create!(name: "Moe's")
12
+ expect(bar.location).to be_nil
13
+ end
14
+
15
+ it 'should set point methodically' do
16
+ bar = Bar.create!(name: "Moe's", location: Mongoid::Geospatial::Point.new)
17
+ bar.location = Mongoid::Geospatial::Point.new(8, 8)
18
+ expect(bar.save).to be_truthy
19
+ expect(Bar.first.location.x).to eq(8)
20
+ end
21
+
22
+ it 'should set point with comma separated text' do
23
+ bar = Bar.create!(name: "Moe's", location: Mongoid::Geospatial::Point.new)
24
+ bar.location = '2.99,3.99'
25
+ expect(bar.location.mongoize).to eq([2.99, 3.99])
26
+ end
27
+
28
+ it 'should set point with space separated text' do
29
+ bar = Bar.create!(name: "Moe's", location: Mongoid::Geospatial::Point.new)
30
+ bar.location = '2.99 3.99'
31
+ expect(bar.location.mongoize).to eq([2.99, 3.99])
32
+ end
33
+
34
+ it 'should set point with space comma separated text' do
35
+ bar = Bar.create!(name: "Moe's", location: Mongoid::Geospatial::Point.new)
36
+ bar.location = '2.99 , 3.99'
37
+ expect(bar.location.mongoize).to eq([2.99, 3.99])
38
+ end
39
+
40
+ it 'should set point to nil' do
41
+ bar = Bar.create!(name: "Moe's", location: [1, 1])
42
+ bar.location = nil
43
+ expect(bar.location).to be_nil
44
+ expect(bar.save).to be_truthy
45
+ expect(Bar.where(location: nil).first).to eq(bar)
46
+ end
47
+
48
+ it 'should set point empty string to nil' do
49
+ bar = Bar.create!(name: "Moe's", location: [1, 1])
50
+ bar.location = ''
51
+ expect(bar.location).to be_nil
52
+ expect(bar.save).to be_truthy
53
+ expect(Bar.where(location: nil).first).to eq(bar)
54
+ end
55
+
56
+ it 'should set point empty array to nil' do
57
+ bar = Bar.create!(name: "Moe's", location: [1, 1])
58
+ bar.location = []
59
+ expect(bar.location).to be_nil
60
+ expect(bar.save).to be_truthy
61
+ expect(Bar.where(location: nil).first).to eq(bar)
62
+ end
63
+
64
+ describe 'methods' do
65
+
66
+ let(:bar) { Bar.create!(location: [3, 2]) }
67
+
68
+ it 'should have a .to_a' do
69
+ expect(bar.location.to_a[0..1]).to eq([3.0, 2.0])
70
+ end
71
+
72
+ it 'should have an array [] accessor' do
73
+ expect(bar.location[0]).to eq(3.0)
74
+ end
75
+
76
+ it 'should have an ActiveModel symbol accessor' do
77
+ expect(bar[:location]).to eq([3, 2])
78
+ end
79
+
80
+ it 'should have a radius helper' do
81
+ expect(bar.location.radius).to eql([[3.0, 2.0], 1])
82
+ end
83
+
84
+ it 'should have a radius sphere helper' do
85
+ expect(bar.location.radius_sphere[1]).to be_within(0.0001).of(0.00015)
86
+ end
87
+
88
+ it 'should have a radius sphere helper in meters' do
89
+ expect(bar.location.radius_sphere(1000, :m)[1]).to be_within(0.0001).of(0.00015)
90
+ end
91
+
92
+ it 'should have a radius sphere helper in miles' do
93
+ expect(bar.location.radius_sphere(1, :mi)[1]).to be_within(0.0001).of(0.00025)
94
+ end
95
+
96
+ end
97
+
98
+ describe 'queryable' do
99
+
100
+ before do
101
+ Bar.create_indexes
102
+ end
103
+
104
+ describe ':near :near_sphere' do
105
+
106
+ let!(:berlin) do
107
+ Bar.create(name: :berlin, location: [52.30, 13.25])
108
+ end
109
+
110
+ let!(:prague) do
111
+ Bar.create(name: :prague, location: [50.5, 14.26])
112
+ end
113
+
114
+ let!(:paris) do
115
+ Bar.create(name: :paris, location: [48.48, 2.20])
116
+ end
117
+
118
+ let!(:jim) do
119
+ Person.new(location: [41.23, 2.9])
120
+ end
121
+
122
+ it 'returns the documents sorted closest to furthest' do
123
+ expect(Bar.where(:location.near => jim.location))
124
+ .to eq([paris, prague, berlin])
125
+ end
126
+
127
+ it 'returns the documents sorted closest to furthest' do
128
+ expect(Bar.near(location: jim.location))
129
+ .to eq([paris, prague, berlin])
130
+ end
131
+
132
+ it 'returns the documents sorted closest to furthest sphere' do
133
+ person = Person.new(location: [41.23, 2.9])
134
+ expect(Bar.near_sphere(location: jim.location))
135
+ .to eq([paris, prague, berlin])
136
+ end
137
+
138
+ it 'returns the documents sorted closest to furthest sphere' do
139
+ person = Person.new(location: [41.23, 2.9])
140
+ expect(Bar.where(:location.near_sphere => jim.location))
141
+ .to eq([paris, prague, berlin])
142
+ end
143
+
144
+ it 'returns the documents sorted closest to furthest with max' do
145
+ expect(Bar.near(location: jim.location).max_distance(location: 10).to_a)
146
+ .to eq([paris]) # , prague, berlin ]
147
+ end
148
+
149
+ end
150
+
151
+ describe ':within_circle :within_spherical_circle' do
152
+ let!(:mile1) do
153
+ Bar.create(name: 'mile1', location: [-73.997345, 40.759382])
154
+ end
155
+
156
+ let!(:mile3) do
157
+ Bar.create(name: 'mile3', location: [-73.927088, 40.752151])
158
+ end
159
+
160
+ let!(:mile7) do
161
+ Bar.create(name: 'mile7', location: [-74.0954913, 40.7161472])
162
+ end
163
+
164
+ let!(:mile9) do
165
+ Bar.create(name: 'mile9', location: [-74.0604951, 40.9178011])
166
+ end
167
+
168
+ let!(:elvis) do
169
+ Person.new(location: [-73.98, 40.75])
170
+ end
171
+
172
+ it 'returns the documents within a center_circle' do
173
+ expect(Bar.where(:location.within_circle =>
174
+ [elvis.location, 250.0 /
175
+ Mongoid::Geospatial::EARTH_RADIUS_KM]).to_a)
176
+ .to eq([mile1])
177
+ end
178
+
179
+ it 'returns the documents within a center_circle' do
180
+ expect(Bar.where(:location.within_circle => [elvis.location,
181
+ 500.0 / Mongoid::Geospatial::EARTH_RADIUS_KM])
182
+ .to_a).to include(mile3)
183
+ end
184
+
185
+ it 'returns the documents within a center_sphere' do
186
+ expect(Bar.where(:location.within_spherical_circle =>
187
+ [elvis.location, 0.0005]).to_a).to eq([mile1])
188
+ end
189
+
190
+ it 'returns the documents within a center_sphere' do
191
+ expect(Bar.where(:location.within_spherical_circle =>
192
+ [elvis.location, 0.5]).to_a).to include(mile9)
193
+ end
194
+
195
+ it 'returns the documents within a box' do
196
+ expect(Bar.within_box(location: [elvis.location,
197
+ elvis.location.map(&:ceil)]).to_a)
198
+ .to eq([mile3])
199
+ end
200
+
201
+ end
202
+
203
+ end
204
+
205
+ describe '(de)mongoize' do
206
+
207
+ it 'should mongoize array' do
208
+ bar = Bar.new(location: [10, -9])
209
+ expect(bar.location.class).to eql(Mongoid::Geospatial::Point)
210
+ expect(bar.location.x).to be_within(0.1).of(10)
211
+ expect(bar.location.y).to be_within(0.1).of(-9)
212
+ end
213
+
214
+ it 'should mongoize hash' do
215
+ geom = Bar.new(location: { x: 10, y: -9 }).location
216
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
217
+ expect(geom.x).to be_within(0.1).of(10)
218
+ expect(geom.y).to be_within(0.1).of(-9)
219
+ end
220
+
221
+ it 'should mongoize hash with symbols in any order' do
222
+ geom = Bar.new(location: { y: -9, x: 10 }).location
223
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
224
+ expect(geom.x).to be_within(0.1).of(10)
225
+ expect(geom.y).to be_within(0.1).of(-9)
226
+ end
227
+
228
+ it 'should mongoize hash with string keys in any order' do
229
+ geom = Bar.new(location: { 'y' => -9, 'x' => 10 }).location
230
+ expect(geom.class).to eql(Mongoid::Geospatial::Point)
231
+ expect(geom.x).to be_within(0.1).of(10)
232
+ expect(geom.y).to be_within(0.1).of(-9)
233
+ end
234
+
235
+ # should raise
236
+ # geom.to_geo
237
+
238
+ describe 'with rgeo' do
239
+
240
+ describe 'instantiated' do
241
+
242
+ let(:bar) { Bar.create!(name: 'Vitinho', location: [10, 10]) }
243
+
244
+ it 'should demongoize to rgeo' do
245
+ expect(bar.location.class).to eql(Mongoid::Geospatial::Point)
246
+ end
247
+
248
+ end
249
+
250
+ end
251
+
252
+ end
253
+
254
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial::Polygon do
4
+
5
+ describe '(de)mongoize' do
6
+
7
+ it 'should support a field mapped as polygon' do
8
+ farm = Farm.new(area: [[5, 5], [6, 5], [6, 6], [5, 6]])
9
+ expect(farm.area).to be_a Mongoid::Geospatial::Polygon
10
+ expect(farm.area).to eq([[5, 5], [6, 5], [6, 6], [5, 6]])
11
+ end
12
+
13
+ it 'should store as array on mongo' do
14
+ Farm.create(area: [[5, 5], [6, 5], [6, 6], [5, 6]])
15
+ expect(Farm.first.area).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::Polygon.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::Polygon.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::Polygon.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::Polygon.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
+ describe 'with rgeo' do
39
+ # farm.area.should be_a RGeo::Geographic::SphericalPolygonImpl
40
+ end
41
+
42
+ end
43
+
44
+ describe 'query' do
45
+
46
+ context ':box, :polygon' do
47
+
48
+ before do
49
+ Farm.create_indexes
50
+ end
51
+
52
+ let!(:ranch) do
53
+ Farm.create(name: 'Ranch', area: [[1, 1], [3, 3]], geom: [2, 2])
54
+ end
55
+
56
+ let!(:farm) do
57
+ Farm.create(name: 'Farm', area: [[47, 1], [49, 1.5], [49, 3], [46, 5]], geom: [47.5, 2.26])
58
+ end
59
+
60
+ it 'returns the documents within a box' do
61
+ expect(Farm.where(:geom.within_polygon =>
62
+ ranch.area).to_a).to eq([ranch])
63
+ end
64
+
65
+ it 'returns the documents within a polygon' do
66
+ expect(Farm.where(:geom.within_polygon =>
67
+ farm.area).to_a).to eq([farm])
68
+ end
69
+
70
+ it 'returns the documents within a center' do
71
+ expect(Farm.where(:geom.within_circle =>
72
+ [ranch.geom, 0.4]).first).to eq(ranch)
73
+ end
74
+
75
+ it 'returns the documents within a center_sphere' do
76
+ expect(Farm.where(:geom.within_spherical_circle =>
77
+ [ranch.geom, 0.1]).first).to eq(ranch)
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Geospatial do
4
+
5
+ context 'Class Stuff' do
6
+
7
+ it 'should have an lng_symbols accessor' do
8
+ expect(Mongoid::Geospatial.lng_symbols).to be_instance_of Array
9
+ expect(Mongoid::Geospatial.lng_symbols).to include :x
10
+ end
11
+
12
+ it 'should have an lat_symbols accessor' do
13
+ expect(Mongoid::Geospatial.lat_symbols).to be_instance_of Array
14
+ expect(Mongoid::Geospatial.lat_symbols).to include :y
15
+ end
16
+
17
+ end
18
+
19
+ context 'Creating indexes' do
20
+
21
+ it 'should create a 2d index' do
22
+ Bar.create_indexes
23
+ expect(Bar.collection.indexes[location: '2d']).not_to be_nil
24
+ end
25
+
26
+ it 'should create a 2dsphere index' do
27
+ Alarm.create_indexes
28
+ expect(Alarm.collection.indexes[spot: '2dsphere']).not_to be_nil
29
+ end
30
+
31
+ end
32
+
33
+ context '#nearby 2d' do
34
+
35
+ before do
36
+ Bar.create_indexes
37
+ end
38
+
39
+ let!(:jfk) do
40
+ Bar.create(name: 'jfk', location: [-73.77694444, 40.63861111])
41
+ end
42
+
43
+ let!(:lax) do
44
+ Bar.create(name: 'lax', location: [-118.40, 33.94])
45
+ end
46
+
47
+ it 'should work with specifying specific center and different location attribute on collction' do
48
+ expect(Bar.nearby(lax.location)).to eq([lax, jfk])
49
+ end
50
+
51
+ end
52
+
53
+ context '#nearby 2dsphere' do
54
+
55
+ before do
56
+ Alarm.create_indexes
57
+ end
58
+
59
+ let!(:jfk) do
60
+ Alarm.create(name: 'jfk', spot: [-73.77694444, 40.63861111])
61
+ end
62
+
63
+ let!(:lax) do
64
+ Alarm.create(name: 'lax', spot: [-118.40, 33.94])
65
+ end
66
+
67
+ it 'should work with specifying specific center and different spot attribute on collction' do
68
+ expect(Alarm.nearby(lax.spot)).to eq([lax, jfk])
69
+ end
70
+
71
+ # context ':maxDistance' do
72
+ # it "should get 1 item" do
73
+ # Bar.geo_near(lax.location, :spherical => true, :max_distance => 2465/Mongoid::Geospatial.earth_radius[:mi]).size.should == 1
74
+ # end
75
+
76
+ # end
77
+
78
+ # context ':distance_multiplier' do
79
+ # it "should multiply returned distance with multiplier" do
80
+ # Bar.geo_near(lax.location, :spherical => true, :distance_multiplier=> Mongoid::Geospatial.earth_radius[:mi]).second.geo[:distance].to_i.should be_within(1).of(2469)
81
+ # end
82
+ # end
83
+
84
+ # context ':unit' do
85
+ # it "should multiply returned distance with multiplier" do
86
+ # Bar.geo_near(lax.location, :spherical => true, :unit => :mi).second.geo[:distance].to_i.should be_within(1).of(2469)
87
+ # end
88
+
89
+ # it "should convert max_distance to radians with unit" do
90
+ # Bar.geo_near(lax.location, :spherical => true, :max_distance => 2465, :unit => :mi).size.should == 1
91
+ # end
92
+
93
+ # end
94
+
95
+ # context ':query' do
96
+ # it "should filter using extra query option" do
97
+ # # two record in the collection, only one's name is Munich
98
+ # Bar.geo_near(jfk.location, :query => {:name => jfk.name}).should == [jfk]
99
+ # end
100
+ # end
101
+
102
+ # end
103
+
104
+ # context 'criteria chaining' do
105
+ # it "should filter by where" do
106
+ # Bar.where(:name => jfk.name).geo_near(jfk.location).should == [jfk]
107
+ # Bar.any_of({:name => jfk.name},{:name => lax.name}).geo_near(jfk.location).should == [jfk,lax]
108
+ # end
109
+
110
+ # it 'should skip 1' do
111
+ # Bar.skip(1).geo_near(jfk.location).size.should == 1
112
+ # end
113
+
114
+ # it 'should limit 1' do
115
+ # Bar.limit(1).geo_near(jfk.location).size.should == 1
116
+ # end
117
+ # end
118
+ # end
119
+
120
+ # context ':paginate' do
121
+ # before do
122
+ # Bar.create_indexes
123
+ # 50.times do
124
+ # Bar.create({:location => [rand(360)-180,rand(360)-180]})
125
+ # end
126
+ # end
127
+
128
+ # [nil,1,2].each do |page|
129
+ # it "page=#{page} should have 25" do
130
+ # Bar.geo_near([1,1], :page => page).size.should == 25
131
+ # end
132
+ # end
133
+
134
+ # it "page=3 should have 0" do
135
+ # Bar.geo_near([1,1], :page => 20).size.should == 0
136
+ # end
137
+
138
+ # it "per_page=5" do
139
+ # Bar.geo_near([1,1], :page => 1, :per_page => 5).size.should == 5
140
+ # end
141
+ end
142
+
143
+ end