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,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