mongoid_spacial 0.0.1

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 (104) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +28 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.md +126 -0
  6. data/Rakefile +42 -0
  7. data/VERSION +1 -0
  8. data/lib/mongoid_spacial.rb +11 -0
  9. data/lib/mongoid_spacial/contexts/mongo.rb +126 -0
  10. data/lib/mongoid_spacial/criteria.rb +5 -0
  11. data/lib/mongoid_spacial/criterion.rb +8 -0
  12. data/lib/mongoid_spacial/criterion/complex.rb +19 -0
  13. data/lib/mongoid_spacial/criterion/inclusion.rb +14 -0
  14. data/lib/mongoid_spacial/criterion/near_spacial.rb +43 -0
  15. data/lib/mongoid_spacial/criterion/within_spacial.rb +56 -0
  16. data/lib/mongoid_spacial/extentions/hash/criteria_helpers.rb +22 -0
  17. data/lib/mongoid_spacial/extentions/symbol/inflections.rb +46 -0
  18. data/lib/mongoid_spacial/field_option.rb +36 -0
  19. data/lib/mongoid_spacial/finders.rb +5 -0
  20. data/lib/mongoid_spacial/spacial.rb +37 -0
  21. data/lib/mongoid_spacial/spacial/core_ext.rb +27 -0
  22. data/lib/mongoid_spacial/spacial/document.rb +31 -0
  23. data/lib/mongoid_spacial/spacial/formulas.rb +47 -0
  24. data/mongoid_spacial.gemspec +172 -0
  25. data/spec/config/mongod.conf +3 -0
  26. data/spec/config/mongoid.yml +18 -0
  27. data/spec/functional/mongoid/contexts/mongo_spec.rb +101 -0
  28. data/spec/functional/mongoid/criterion/inclusion_spec.rb +356 -0
  29. data/spec/models/account.rb +19 -0
  30. data/spec/models/acolyte.rb +9 -0
  31. data/spec/models/address.rb +62 -0
  32. data/spec/models/address_component.rb +5 -0
  33. data/spec/models/agent.rb +10 -0
  34. data/spec/models/alert.rb +5 -0
  35. data/spec/models/animal.rb +21 -0
  36. data/spec/models/answer.rb +4 -0
  37. data/spec/models/bar.rb +9 -0
  38. data/spec/models/birthday.rb +13 -0
  39. data/spec/models/book.rb +5 -0
  40. data/spec/models/business.rb +7 -0
  41. data/spec/models/callbacks.rb +57 -0
  42. data/spec/models/category.rb +13 -0
  43. data/spec/models/circus.rb +7 -0
  44. data/spec/models/comment.rb +13 -0
  45. data/spec/models/country_code.rb +6 -0
  46. data/spec/models/description.rb +11 -0
  47. data/spec/models/division.rb +5 -0
  48. data/spec/models/drug.rb +5 -0
  49. data/spec/models/employer.rb +5 -0
  50. data/spec/models/entry.rb +6 -0
  51. data/spec/models/event.rb +20 -0
  52. data/spec/models/favorite.rb +6 -0
  53. data/spec/models/fruits.rb +11 -0
  54. data/spec/models/game.rb +18 -0
  55. data/spec/models/ghost.rb +7 -0
  56. data/spec/models/house.rb +4 -0
  57. data/spec/models/inheritance.rb +90 -0
  58. data/spec/models/league.rb +5 -0
  59. data/spec/models/location.rb +5 -0
  60. data/spec/models/login.rb +6 -0
  61. data/spec/models/membership.rb +4 -0
  62. data/spec/models/mixed_drink.rb +4 -0
  63. data/spec/models/name.rb +13 -0
  64. data/spec/models/namespacing.rb +11 -0
  65. data/spec/models/observed.rb +41 -0
  66. data/spec/models/override.rb +16 -0
  67. data/spec/models/owner.rb +6 -0
  68. data/spec/models/page.rb +5 -0
  69. data/spec/models/page_question.rb +4 -0
  70. data/spec/models/paranoid_post.rb +18 -0
  71. data/spec/models/parents.rb +32 -0
  72. data/spec/models/patient.rb +15 -0
  73. data/spec/models/person.rb +146 -0
  74. data/spec/models/pet.rb +7 -0
  75. data/spec/models/pet_owner.rb +6 -0
  76. data/spec/models/phone.rb +7 -0
  77. data/spec/models/player.rb +23 -0
  78. data/spec/models/post.rb +26 -0
  79. data/spec/models/preference.rb +9 -0
  80. data/spec/models/question.rb +8 -0
  81. data/spec/models/quiz.rb +6 -0
  82. data/spec/models/rating.rb +8 -0
  83. data/spec/models/river.rb +20 -0
  84. data/spec/models/role.rb +5 -0
  85. data/spec/models/service.rb +6 -0
  86. data/spec/models/shelf.rb +5 -0
  87. data/spec/models/slave_address_numbers.rb +14 -0
  88. data/spec/models/survey.rb +5 -0
  89. data/spec/models/tag.rb +6 -0
  90. data/spec/models/tracking_id_validation_history.rb +25 -0
  91. data/spec/models/translation.rb +5 -0
  92. data/spec/models/tree.rb +9 -0
  93. data/spec/models/user.rb +9 -0
  94. data/spec/models/user_account.rb +10 -0
  95. data/spec/models/vet_visit.rb +5 -0
  96. data/spec/models/video.rb +9 -0
  97. data/spec/models/wiki_page.rb +6 -0
  98. data/spec/spec_helper.rb +41 -0
  99. data/spec/support/authentication.rb +29 -0
  100. data/spec/unit/mongoid_spacial/criterion/complex_spec.rb +15 -0
  101. data/spec/unit/mongoid_spacial/criterion/inclusion_spec.rb +0 -0
  102. data/spec/unit/mongoid_spacial/criterion/near_spacial_spec.rb +39 -0
  103. data/spec/unit/mongoid_spacial/criterion/within_spacial_spec.rb +52 -0
  104. metadata +280 -0
@@ -0,0 +1,3 @@
1
+ dbpath = /usr/local/var/mongodb
2
+ master = true
3
+ bind_ip = 127.0.0.1
@@ -0,0 +1,18 @@
1
+ test:
2
+ database: mongoid_config_test
3
+ host: localhost
4
+ slaves:
5
+ # - host: localhost
6
+ # port: 27018
7
+ # - host: localhost
8
+ # port: 27019
9
+ allow_dynamic_fields: false
10
+ include_root_in_json: true
11
+ parameterize_keys: false
12
+ persist_in_safe_mode: false
13
+ raise_not_found_error: false
14
+ reconnect_time: 5
15
+ autocreate_indexes: false
16
+ persist_types: false
17
+ option_no_exist: false
18
+ skip_version_check: false
@@ -0,0 +1,101 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Contexts::Mongo do
4
+
5
+ before do
6
+ Bar.delete_all
7
+ Bar.create_indexes
8
+ end
9
+
10
+ let!(:munich) do
11
+ Bar.create(:location => [45, 11], :name => 'Munich')
12
+ end
13
+
14
+ let!(:berlin) do
15
+ Bar.create(:location => [46, 12], :name => 'Berlin')
16
+ end
17
+ describe "geo_near" do
18
+ it "should work with specifying specific center and different location attribute on collction" do
19
+ location = [-47,23.5]
20
+ near = Bar.geo_near(location)
21
+ near.should == [munich,berlin]
22
+ near.first.geo[:distance].should > 0
23
+ end
24
+
25
+ describe 'option :num' do
26
+ it "should limit number of results to 1" do
27
+ location = [-47,23.5]
28
+ Bar.geo_near(location, :num => 1).size.should == 1
29
+ end
30
+ end
31
+
32
+ describe 'option :maxDistance' do
33
+ it "should limit on maximum distance" do
34
+ location = [45.1, 11.1]
35
+ # db.runCommand({ geo_near : "points", near :[45.1, 11.1]}).results;
36
+ # dis: is 0.14141869255648362 and 1.2727947855285668
37
+ Bar.geo_near(location, :max_distance => 0.2).should == [munich]
38
+ end
39
+ end
40
+
41
+ describe 'option :distanceMultiplier' do
42
+ it "should multiply returned distance with multiplier" do
43
+ location = [45.1, 11.1]
44
+ Bar.geo_near(location, :distance_multiplier => 4).first.geo[:distance].should > 0
45
+ end
46
+ end
47
+
48
+ describe 'option :unit' do
49
+ it "should multiply returned distance with multiplier" do
50
+ location = [45.1, 11.1]
51
+ distance = Bar.geo_near(location, :unit => :mi).first.geo[:distance]
52
+ distance.should > 559
53
+ distance.should < 560
54
+ end
55
+
56
+ it "should convert max_distance to radians with unit" do
57
+ location = [45.1, 11.1]
58
+ near = Bar.geo_near(location, :max_distance => 570, :unit => :mi)
59
+ near.size.should == 1
60
+ near.first.should == munich
61
+ end
62
+
63
+ it "should convert max_distance to radians with unit" do
64
+ location = [45.1, 11.1]
65
+ Bar.geo_near(location, :max_distance => 570, :distance_multiplier => 4, :unit => :mi).first.should == munich
66
+ end
67
+
68
+ end
69
+
70
+ describe 'option :query' do
71
+ it "should filter using extra query option" do
72
+ location = [45.1, 11.1]
73
+ # two record in the collection, only one's name is Munich
74
+ Bar.geo_near(location, :query => {:name => 'Munich'}).size.should == 1
75
+ end
76
+ end
77
+
78
+ describe 'criteria chaining' do
79
+ it "should filter by where" do
80
+ location = [45.1, 11.1]
81
+ # two record in the collection, only one's name is Munich
82
+ a = Bar.where(:name => 'Munich')
83
+ # p a.selector
84
+ # a.geo_near(location).size.should == 1
85
+ end
86
+
87
+ it 'should skip 1' do
88
+ location = [-47,23.5]
89
+ Bar.skip(1).geo_near(location).size.should == 1
90
+ end
91
+
92
+ it 'should limit 1' do
93
+ location = [-47,23.5]
94
+ Bar.limit(1).geo_near(location).size.should == 1
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+ end
101
+
@@ -0,0 +1,356 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criterion::Inclusion do
4
+
5
+ before do
6
+ Person.delete_all
7
+ end
8
+
9
+ describe "#where" do
10
+
11
+ let(:dob) do
12
+ 33.years.ago.to_date
13
+ end
14
+
15
+ let(:lunch_time) do
16
+ 30.minutes.ago
17
+ end
18
+
19
+ let!(:person) do
20
+ Person.create(
21
+ :title => "Sir",
22
+ :dob => dob,
23
+ :lunch_time => lunch_time,
24
+ :age => 33,
25
+ :aliases => [ "D", "Durran" ],
26
+ :things => [ { :phone => 'HTC Incredible' } ]
27
+ )
28
+ end
29
+
30
+ context "when providing 24 character strings" do
31
+
32
+ context "when the field is not an id field" do
33
+
34
+ let(:string) do
35
+ BSON::ObjectId.new.to_s
36
+ end
37
+
38
+ let!(:person) do
39
+ Person.create(:title => string)
40
+ end
41
+
42
+ let(:from_db) do
43
+ Person.where(:title => string)
44
+ end
45
+
46
+ it "does not convert the field to a bson id" do
47
+ from_db.should == [ person ]
48
+ end
49
+ end
50
+ end
51
+
52
+ context "when providing string object ids" do
53
+
54
+ context "when providing a single id" do
55
+
56
+ let(:from_db) do
57
+ Person.where(:_id => person.id.to_s).first
58
+ end
59
+
60
+ it "returns the matching documents" do
61
+ from_db.should == person
62
+ end
63
+ end
64
+ end
65
+
66
+ context "chaining multiple wheres" do
67
+
68
+ context "when chaining on the same key" do
69
+
70
+ let(:from_db) do
71
+ Person.where(:title => "Maam").where(:title => "Sir")
72
+ end
73
+
74
+ it "overrides the previous key" do
75
+ from_db.should == [ person ]
76
+ end
77
+ end
78
+
79
+ context "with different criteria on the same key" do
80
+
81
+ it "merges criteria" do
82
+ Person.where(:age.gt => 30).where(:age.lt => 40).should == [person]
83
+ end
84
+
85
+ it "typecasts criteria" do
86
+ before_dob = (dob - 1.month).to_s
87
+ after_dob = (dob + 1.month).to_s
88
+ Person.where(:dob.gt => before_dob).and(:dob.lt => after_dob).should == [person]
89
+ end
90
+
91
+ end
92
+ end
93
+
94
+ context "with untyped criteria" do
95
+
96
+ it "typecasts integers" do
97
+ Person.where(:age => "33").should == [ person ]
98
+ end
99
+
100
+ it "typecasts datetimes" do
101
+ Person.where(:lunch_time => lunch_time.to_s).should == [ person ]
102
+ end
103
+
104
+ it "typecasts dates" do
105
+ Person.where({:dob => dob.to_s}).should == [ person ]
106
+ end
107
+
108
+ it "typecasts times with zones" do
109
+ time = lunch_time.in_time_zone("Alaska")
110
+ Person.where(:lunch_time => time).should == [ person ]
111
+ end
112
+
113
+ it "typecasts array elements" do
114
+ Person.where(:age.in => [17, "33"]).should == [ person ]
115
+ end
116
+
117
+ it "typecasts size criterion to integer" do
118
+ Person.where(:aliases.size => "2").should == [ person ]
119
+ end
120
+
121
+ it "typecasts exists criterion to boolean" do
122
+ Person.where(:score.exists => "f").should == [ person ]
123
+ end
124
+ end
125
+
126
+ context "with multiple complex criteria" do
127
+
128
+ before do
129
+ Person.create(:title => "Mrs", :age => 29)
130
+ Person.create(:title => "Ms", :age => 41)
131
+ end
132
+
133
+ it "returns those matching both criteria" do
134
+ Person.where(:age.gt => 30, :age.lt => 40).should == [person]
135
+ end
136
+
137
+ it "returns nothing if in and nin clauses cancel each other out" do
138
+ Person.any_in(:title => ["Sir"]).not_in(:title => ["Sir"]).should == []
139
+ end
140
+
141
+ it "returns nothing if in and nin clauses cancel each other out ordered the other way" do
142
+ Person.not_in(:title => ["Sir"]).any_in(:title => ["Sir"]).should == []
143
+ end
144
+
145
+ it "returns the intersection of in and nin clauses" do
146
+ Person.any_in(:title => ["Sir", "Mrs"]).not_in(:title => ["Mrs"]).should == [person]
147
+ end
148
+
149
+ it "returns the intersection of two in clauses" do
150
+ Person.where(:title.in => ["Sir", "Mrs"]).where(:title.in => ["Sir", "Ms"]).should == [person]
151
+ end
152
+ end
153
+
154
+ context "with complex criterion" do
155
+
156
+ context "#all" do
157
+
158
+ it "returns those matching an all clause" do
159
+ Person.where(:aliases.all => ["D", "Durran"]).should == [person]
160
+ end
161
+ end
162
+
163
+ context "#exists" do
164
+
165
+ it "returns those matching an exists clause" do
166
+ Person.where(:title.exists => true).should == [person]
167
+ end
168
+ end
169
+
170
+ context "#gt" do
171
+
172
+ it "returns those matching a gt clause" do
173
+ Person.where(:age.gt => 30).should == [person]
174
+ end
175
+ end
176
+
177
+ context "#gte" do
178
+
179
+ it "returns those matching a gte clause" do
180
+ Person.where(:age.gte => 33).should == [person]
181
+ end
182
+ end
183
+
184
+ context "#in" do
185
+
186
+ it "returns those matching an in clause" do
187
+ Person.where(:title.in => ["Sir", "Madam"]).should == [person]
188
+ end
189
+
190
+ it "allows nil" do
191
+ Person.where(:ssn.in => [nil]).should == [person]
192
+ end
193
+ end
194
+
195
+ context "#lt" do
196
+
197
+ it "returns those matching a lt clause" do
198
+ Person.where(:age.lt => 34).should == [person]
199
+ end
200
+ end
201
+
202
+ context "#lte" do
203
+
204
+ it "returns those matching a lte clause" do
205
+ Person.where(:age.lte => 33).should == [person]
206
+ end
207
+ end
208
+
209
+ context "#ne" do
210
+
211
+ it "returns those matching a ne clause" do
212
+ Person.where(:age.ne => 50).should == [person]
213
+ end
214
+ end
215
+
216
+ context "#nin" do
217
+
218
+ it "returns those matching a nin clause" do
219
+ Person.where(:title.nin => ["Esquire", "Congressman"]).should == [person]
220
+ end
221
+ end
222
+
223
+ context "#size" do
224
+
225
+ it "returns those matching a size clause" do
226
+ Person.where(:aliases.size => 2).should == [person]
227
+ end
228
+ end
229
+
230
+ context "#match" do
231
+
232
+ it "returns those matching a partial element in a list" do
233
+ Person.where(:things.matches => { :phone => "HTC Incredible" }).should == [person]
234
+ end
235
+ end
236
+
237
+ end
238
+
239
+ context "Geo Spacial Complex Where" do
240
+
241
+ let!(:home) do
242
+ [-73.98,40.77]
243
+ end
244
+
245
+ describe "#near" do
246
+ before do
247
+ Bar.delete_all
248
+ Bar.create_indexes
249
+ end
250
+
251
+ let!(:berlin) do
252
+ Bar.create(:location => [ 52.30, 13.25 ])
253
+ end
254
+
255
+ let!(:prague) do
256
+ Bar.create(:location => [ 50.5, 14.26 ])
257
+ end
258
+
259
+ let!(:paris) do
260
+ Bar.create(:location => [ 48.48, 2.20 ])
261
+ end
262
+
263
+ it "returns the documents sorted closest to furthest" do
264
+ Bar.where(:location.near => [ 41.23, 2.9 ]).should == [ paris, prague, berlin ]
265
+ end
266
+
267
+ it "returns the documents sorted closest to furthest" do
268
+ Bar.where(:location.near => {:point=>[ 41.23, 2.9 ],:max => 20}).should == [ paris, prague, berlin ]
269
+ end
270
+
271
+ it "returns the documents sorted closest to furthest" do
272
+ Bar.where(:location.near_sphere => [ 41.23, 2.9 ]).should == [ paris, prague, berlin ]
273
+ end
274
+
275
+ end
276
+
277
+ context "#within" do
278
+
279
+ context ":box, :polygon" do
280
+ before do
281
+ Bar.delete_all
282
+ Bar.create_indexes
283
+ end
284
+
285
+ let!(:berlin) do
286
+ Bar.create(:name => 'berlin', :location => [ 52.30, 13.25 ])
287
+ end
288
+
289
+ let!(:prague) do
290
+ Bar.create(:name => 'prague',:location => [ 50.5, 14.26 ])
291
+ end
292
+
293
+ let!(:paris) do
294
+ Bar.create(:name => 'prague',:location => [ 48.48, 2.20 ])
295
+ end
296
+
297
+ it "returns the documents within a box" do
298
+ Bar.where(:location.within(:box) => [[ 47, 1 ],[ 49, 3 ]]).should == [ paris ]
299
+ end
300
+
301
+ it "returns the documents within a polygon", :if => (Mongoid.master.connection.server_version >= '1.9') do
302
+ Bar.where(:location.within(:polygon) => [[ 47, 1 ],[49,1.5],[ 49, 3 ],[46,5]]).should == [ paris ]
303
+ end
304
+
305
+ it "returns the documents within a center" do
306
+ Bar.where(:location.within(:center) => [[ 47, 1 ],4]).should == [ paris ]
307
+ end
308
+
309
+ it "returns the documents within a center_sphere" do
310
+ Bar.where(:location.within(:center_sphere) => [[ 48, 2 ],0.1]).should == [ paris ]
311
+ end
312
+
313
+ end
314
+ context ":circle :center_sphere" do
315
+ before do
316
+ Bar.delete_all
317
+ Bar.create_indexes
318
+ end
319
+ let!(:mile1) do
320
+ Bar.create(:name => 'mile1', :location => [-73.997345, 40.759382])
321
+ end
322
+
323
+ let!(:mile3) do
324
+ Bar.create(:name => 'mile2', :location => [-73.927088, 40.752151])
325
+ end
326
+
327
+ let!(:mile7) do
328
+ Bar.create(:name => 'mile3', :location => [-74.0954913, 40.7161472])
329
+ end
330
+
331
+ let!(:mile11) do
332
+ Bar.create(:name => 'mile4', :location => [-74.0604951, 40.9178011])
333
+ end
334
+
335
+ it "returns the documents within a center_sphere" do
336
+ Bar.where(:location.within(:center_sphere) => {:point => home,:max => 2, :unit => :mi}).should == [ mile1 ]
337
+ end
338
+
339
+ it "returns the documents within a center_sphere" do
340
+ Bar.where(:location.within(:center_sphere) => {:point => home,:max => 4, :unit => :mi}).should include(mile3)
341
+ end
342
+
343
+ it "returns the documents within a center_sphere" do
344
+ Bar.where(:location.within(:center_sphere) => {:point => home,:max => 8, :unit => :mi}).should include(mile7)
345
+ end
346
+
347
+ it "returns the documents within a center_sphere" do
348
+ Bar.where(:location.within(:center_sphere) => {:point => home,:max => 12, :unit => :mi}).should include(mile11)
349
+ end
350
+ end
351
+ end
352
+ end
353
+
354
+ end
355
+
356
+ end