mongoid-geospatial 5.0.0 → 7.0.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.
- checksums.yaml +5 -5
- data/.rubocop.yml +8 -0
- data/.travis.yml +26 -20
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +118 -0
- data/Gemfile +8 -16
- data/Guardfile +2 -2
- data/MIT-LICENSE +2 -2
- data/README.md +202 -212
- data/RELEASING.md +62 -0
- data/Rakefile +4 -1
- data/lib/mongoid/geospatial/config/point.rb +19 -0
- data/lib/mongoid/geospatial/config.rb +29 -0
- data/lib/mongoid/geospatial/fields/circle.rb +3 -3
- data/lib/mongoid/geospatial/fields/point.rb +29 -10
- data/lib/mongoid/geospatial/geometry_field.rb +6 -4
- data/lib/mongoid/geospatial/helpers/sphere.rb +1 -1
- data/lib/mongoid/geospatial/version.rb +1 -1
- data/lib/mongoid/geospatial/wrappers/georuby.rb +1 -0
- data/lib/mongoid/geospatial.rb +107 -30
- data/mongoid-geospatial.gemspec +3 -4
- data/{bench → spec}/bench +1 -1
- data/spec/models/bar.rb +1 -0
- data/spec/models/event.rb +1 -1
- data/spec/models/farm.rb +1 -1
- data/spec/models/person.rb +2 -9
- data/spec/models/river.rb +7 -7
- data/spec/mongoid/geospatial/config_spec.rb +22 -0
- data/spec/mongoid/geospatial/fields/line_string_spec.rb +3 -4
- data/spec/mongoid/geospatial/fields/point_spec.rb +50 -4
- data/spec/mongoid/geospatial/fields/polygon_spec.rb +3 -3
- data/spec/mongoid/geospatial/geospatial_spec.rb +80 -8
- data/spec/mongoid/geospatial/helpers/core_spec.rb +6 -3
- data/spec/mongoid/geospatial/helpers/spatial_spec.rb +3 -3
- data/spec/mongoid/geospatial/helpers/sphere_spec.rb +6 -6
- data/spec/mongoid.yml +298 -0
- data/spec/spec_helper.rb +9 -19
- data/spec/support/authentication.rb +0 -1
- metadata +18 -12
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Geospatial
|
3
|
+
module Config
|
4
|
+
autoload :Point, 'mongoid/geospatial/config/point'
|
5
|
+
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def reset!
|
9
|
+
Mongoid::Geospatial::Config::Point.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
def point
|
13
|
+
Mongoid::Geospatial::Config::Point
|
14
|
+
end
|
15
|
+
|
16
|
+
reset!
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def configure
|
21
|
+
block_given? ? yield(Config) : Config
|
22
|
+
end
|
23
|
+
|
24
|
+
def config
|
25
|
+
Config
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -18,10 +18,11 @@ module Mongoid
|
|
18
18
|
# @return (Array)
|
19
19
|
def mongoize
|
20
20
|
return nil unless x && y
|
21
|
+
|
21
22
|
[x, y]
|
22
23
|
end
|
23
|
-
|
24
|
-
|
24
|
+
alias to_a mongoize
|
25
|
+
alias to_xy mongoize
|
25
26
|
|
26
27
|
def [](args)
|
27
28
|
mongoize[args]
|
@@ -40,7 +41,7 @@ module Mongoid
|
|
40
41
|
def to_hsh(xl = :x, yl = :y)
|
41
42
|
{ xl => x, yl => y }
|
42
43
|
end
|
43
|
-
|
44
|
+
alias to_hash to_hsh
|
44
45
|
|
45
46
|
#
|
46
47
|
# Helper for [self, radius]
|
@@ -48,7 +49,7 @@ module Mongoid
|
|
48
49
|
# @return [Array] with [self, radius]
|
49
50
|
#
|
50
51
|
def radius(r = 1)
|
51
|
-
[mongoize, r]
|
52
|
+
[ mongoize, r ]
|
52
53
|
end
|
53
54
|
|
54
55
|
#
|
@@ -84,6 +85,18 @@ module Mongoid
|
|
84
85
|
"#{x}, #{y}"
|
85
86
|
end
|
86
87
|
|
88
|
+
#
|
89
|
+
# Point definition as GeoJSON
|
90
|
+
#
|
91
|
+
# "x, y"
|
92
|
+
#
|
93
|
+
# @return [String] Point as comma separated String
|
94
|
+
#
|
95
|
+
def to_geo_json
|
96
|
+
# Return a GeoJSON point hash that MongoDB can use
|
97
|
+
{ type: "Point", coordinates: [x, y] }
|
98
|
+
end
|
99
|
+
|
87
100
|
#
|
88
101
|
# Point inverse/reverse
|
89
102
|
#
|
@@ -144,7 +157,8 @@ module Mongoid
|
|
144
157
|
when NilClass then nil
|
145
158
|
else
|
146
159
|
return obj.to_xy if obj.respond_to?(:to_xy)
|
147
|
-
|
160
|
+
|
161
|
+
raise 'Invalid Point'
|
148
162
|
end
|
149
163
|
end
|
150
164
|
|
@@ -171,6 +185,7 @@ module Mongoid
|
|
171
185
|
#
|
172
186
|
def from_string(str)
|
173
187
|
return nil if str.empty?
|
188
|
+
|
174
189
|
str.split(/,|\s/).reject(&:empty?).map(&:to_f)
|
175
190
|
end
|
176
191
|
|
@@ -185,6 +200,7 @@ module Mongoid
|
|
185
200
|
#
|
186
201
|
def from_array(array)
|
187
202
|
return nil if array.empty?
|
203
|
+
|
188
204
|
array.flatten[0..1].map(&:to_f)
|
189
205
|
end
|
190
206
|
|
@@ -203,20 +219,23 @@ module Mongoid
|
|
203
219
|
# @return (Array)
|
204
220
|
#
|
205
221
|
def from_hash(hsh)
|
206
|
-
|
222
|
+
raise 'Hash must have at least 2 items' if hsh.size < 2
|
223
|
+
|
207
224
|
[from_hash_x(hsh), from_hash_y(hsh)]
|
208
225
|
end
|
209
226
|
|
210
227
|
def from_hash_y(hsh)
|
211
|
-
v = (Mongoid::Geospatial.
|
228
|
+
v = (Mongoid::Geospatial::Config::Point.y & hsh.keys).first
|
212
229
|
return hsh[v].to_f if !v.nil? && hsh[v]
|
213
|
-
|
230
|
+
|
231
|
+
raise "Hash must contain #{Mongoid::Geospatial::Config::Point.y.inspect}"
|
214
232
|
end
|
215
233
|
|
216
234
|
def from_hash_x(hsh)
|
217
|
-
v = (Mongoid::Geospatial.
|
235
|
+
v = (Mongoid::Geospatial::Config::Point.x & hsh.keys).first
|
218
236
|
return hsh[v].to_f if !v.nil? && hsh[v]
|
219
|
-
|
237
|
+
|
238
|
+
raise "Hash must contain #{Mongoid::Geospatial::Config::Point.x.inspect}"
|
220
239
|
end
|
221
240
|
end # << self
|
222
241
|
end # Point
|
@@ -17,8 +17,10 @@ module Mongoid
|
|
17
17
|
# @return [Array] containing 2 points
|
18
18
|
#
|
19
19
|
def bounding_box
|
20
|
-
max_x
|
21
|
-
|
20
|
+
max_x = -Float::MAX
|
21
|
+
min_x = Float::MAX
|
22
|
+
max_y = -Float::MAX
|
23
|
+
min_y = Float::MAX
|
22
24
|
each do |point|
|
23
25
|
max_y = point[1] if point[1] > max_y
|
24
26
|
min_y = point[1] if point[1] < min_y
|
@@ -27,7 +29,7 @@ module Mongoid
|
|
27
29
|
end
|
28
30
|
[[min_x, min_y], [max_x, max_y]]
|
29
31
|
end
|
30
|
-
|
32
|
+
alias bbox bounding_box
|
31
33
|
|
32
34
|
#
|
33
35
|
# Determines the 5 points geometry bounding box.
|
@@ -53,7 +55,7 @@ module Mongoid
|
|
53
55
|
min, max = *bbox
|
54
56
|
[(min[0] + max[0]) / 2.0, (min[1] + max[1]) / 2.0]
|
55
57
|
end
|
56
|
-
|
58
|
+
alias center center_point
|
57
59
|
|
58
60
|
#
|
59
61
|
# Generates a radius from the point
|
data/lib/mongoid/geospatial.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'mongoid'
|
2
|
-
|
3
|
-
# require 'active_support/concern'
|
2
|
+
require 'active_support/concern' # Explicitly require for `extend ActiveSupport::Concern`
|
4
3
|
require 'mongoid/geospatial/helpers/spatial'
|
5
4
|
require 'mongoid/geospatial/helpers/sphere'
|
6
5
|
require 'mongoid/geospatial/helpers/delegate'
|
@@ -27,10 +26,10 @@ module Mongoid
|
|
27
26
|
|
28
27
|
# Symbols accepted as 'longitude', 'x'...
|
29
28
|
LNG_SYMBOLS = [:x, :lon, :long, :lng, :longitude,
|
30
|
-
'x', 'lon', 'long', 'lng', 'longitude']
|
29
|
+
'x', 'lon', 'long', 'lng', 'longitude'].freeze
|
31
30
|
|
32
31
|
# Symbols accepted as 'latitude', 'y'...
|
33
|
-
LAT_SYMBOLS = [:y, :lat, :latitude, 'y', 'lat', 'latitude']
|
32
|
+
LAT_SYMBOLS = [:y, :lat, :latitude, 'y', 'lat', 'latitude'].freeze
|
34
33
|
|
35
34
|
# For distance spherical calculations
|
36
35
|
EARTH_RADIUS_KM = 6371 # taken directly from mongodb
|
@@ -38,12 +37,12 @@ module Mongoid
|
|
38
37
|
|
39
38
|
# Earth radius in multiple units
|
40
39
|
EARTH_RADIUS = {
|
41
|
-
m:
|
40
|
+
m: EARTH_RADIUS_KM * 1000,
|
42
41
|
km: EARTH_RADIUS_KM,
|
43
42
|
mi: EARTH_RADIUS_KM * 0.621371192,
|
44
43
|
ft: EARTH_RADIUS_KM * 5280 * 0.621371192,
|
45
44
|
sm: EARTH_RADIUS_KM * 0.53995680345572 # sea mile
|
46
|
-
}
|
45
|
+
}.freeze
|
47
46
|
|
48
47
|
mattr_accessor :lng_symbols
|
49
48
|
mattr_accessor :lat_symbols
|
@@ -55,7 +54,6 @@ module Mongoid
|
|
55
54
|
@@earth_radius = EARTH_RADIUS.dup
|
56
55
|
|
57
56
|
included do
|
58
|
-
# attr_accessor :geo
|
59
57
|
cattr_accessor :spatial_fields, :spatial_fields_indexed
|
60
58
|
self.spatial_fields = []
|
61
59
|
self.spatial_fields_indexed = []
|
@@ -72,14 +70,10 @@ module Mongoid
|
|
72
70
|
# Methods applied to Document's class
|
73
71
|
module ClassMethods
|
74
72
|
#
|
75
|
-
#
|
73
|
+
# Creates a 2d spatial index for the given field.
|
76
74
|
#
|
77
|
-
#
|
78
|
-
# @param [
|
79
|
-
# @param [Hash] options options for spatial_index
|
80
|
-
#
|
81
|
-
# http://www.mongodb.org/display/DOCS/Geospatial+Indexing
|
82
|
-
# #GeospatialIndexing-geoNearCommand
|
75
|
+
# @param name [String, Symbol] The name of the field to index.
|
76
|
+
# @param options [Hash] Additional options for the index.
|
83
77
|
#
|
84
78
|
def spatial_index(name, options = {})
|
85
79
|
spatial_fields_indexed << name
|
@@ -87,36 +81,119 @@ module Mongoid
|
|
87
81
|
end
|
88
82
|
|
89
83
|
#
|
90
|
-
# Creates
|
91
|
-
#
|
84
|
+
# Creates a 2dsphere index for the given field, suitable for spherical geometry calculations.
|
92
85
|
#
|
93
|
-
# @param [String,Symbol] name
|
94
|
-
# @param [Hash]
|
86
|
+
# @param name [String, Symbol] The name of the field to index.
|
87
|
+
# @param options [Hash] Additional options for the index.
|
95
88
|
#
|
96
|
-
|
97
|
-
# #GeospatialIndexing-geoNearCommand
|
98
|
-
def sphere_index(name, options = {})
|
89
|
+
def spherical_index(name, options = {})
|
99
90
|
spatial_fields_indexed << name
|
100
91
|
index({ name => '2dsphere' }, options)
|
101
92
|
end
|
102
93
|
|
103
94
|
#
|
104
|
-
#
|
95
|
+
# Defines a class method to find the closest document to a given point
|
96
|
+
# using the specified spatial field via the `geoNear` command.
|
105
97
|
#
|
98
|
+
# @param field_name [String, Symbol] The name of the spatial field to query.
|
99
|
+
# @param default_geo_near_options [Hash] Default options for the geoNear command
|
100
|
+
# (e.g., `{ spherical: true, max_distance: 1000 }`).
|
101
|
+
# The `key` option will be automatically set to `field_name`.
|
106
102
|
#
|
107
|
-
#
|
108
|
-
#
|
103
|
+
# Example:
|
104
|
+
# class Place
|
105
|
+
# include Mongoid::Document
|
106
|
+
# include Mongoid::Geospatial
|
107
|
+
# field :location, type: Array
|
108
|
+
# spherical_index :location # Assumes a 2dsphere index for spherical queries
|
109
|
+
# spatial_scope :location, spherical: true # Default to spherical for this scope
|
110
|
+
# end
|
109
111
|
#
|
110
|
-
#
|
111
|
-
# #
|
112
|
-
|
112
|
+
# Place.closest_to_location([lon, lat]) # Finds the single closest place
|
113
|
+
# Place.closest_to_location([lon, lat], max_distance: 500) # Override/add options
|
114
|
+
#
|
115
|
+
def spatial_scope(field_name, default_geo_near_options = {})
|
116
|
+
method_name = :"closest_to_#{field_name}"
|
117
|
+
field_name_sym = field_name.to_sym
|
118
|
+
# key_name = field_name.to_s # Original geoNear used 'key' for field name
|
119
|
+
|
113
120
|
singleton_class.class_eval do
|
114
|
-
|
115
|
-
|
116
|
-
|
121
|
+
define_method(method_name) do |coordinates, additional_options = {}|
|
122
|
+
# `coordinates` should be [lon, lat] or a GeoJSON Point hash
|
123
|
+
# `self` here is the class (e.g., Bar)
|
124
|
+
|
125
|
+
merged_options = default_geo_near_options.merge(additional_options)
|
126
|
+
|
127
|
+
# Determine if spherical based on options or field definition
|
128
|
+
is_spherical = if merged_options.key?(:spherical)
|
129
|
+
merged_options[:spherical]
|
130
|
+
else
|
131
|
+
# self.fields uses string keys for field names
|
132
|
+
field_def = self.fields[field_name.to_s]
|
133
|
+
field_def && field_def.options[:sphere]
|
134
|
+
end
|
135
|
+
query_operator = is_spherical ? :near_sphere : :near
|
136
|
+
|
137
|
+
# Prepare the value for the geospatial operator
|
138
|
+
# Mongoid::Geospatial::Point.mongoize ensures coordinates are in [lng, lat] array format
|
139
|
+
# from various input types (Point object, array, string, hash).
|
140
|
+
mongoized_coords = Mongoid::Geospatial::Point.mongoize(coordinates)
|
141
|
+
|
142
|
+
geo_query_value = if merged_options[:max_distance]
|
143
|
+
{
|
144
|
+
# Using $geometry for clarity when $maxDistance is used,
|
145
|
+
# which is standard for $near/$nearSphere operators.
|
146
|
+
"$geometry" => { type: "Point", coordinates: mongoized_coords },
|
147
|
+
"$maxDistance" => merged_options[:max_distance].to_f
|
148
|
+
}
|
149
|
+
else
|
150
|
+
mongoized_coords # Simple array [lng, lat] for the operator
|
151
|
+
end
|
152
|
+
|
153
|
+
# Start with a base criteria, applying an optional filter query
|
154
|
+
current_criteria = merged_options[:query] ? self.where(merged_options[:query]) : self.all
|
155
|
+
|
156
|
+
# Apply the geospatial query. $near and $nearSphere queries return sorted results.
|
157
|
+
current_criteria.where(field_name_sym.send(query_operator) => geo_query_value)
|
117
158
|
end
|
118
159
|
end
|
119
160
|
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Provides a convenient way to find documents near a given set of coordinates.
|
164
|
+
# It automatically uses the first spatial field defined in the model and
|
165
|
+
# determines whether to use a planar (.near) or spherical (.near_sphere)
|
166
|
+
# query based on the field's definition options (`spatial: true` vs `sphere: true`).
|
167
|
+
#
|
168
|
+
# @param coordinates [Array, Mongoid::Geospatial::Point] The coordinates (e.g., [lon, lat])
|
169
|
+
# or a Point object to find documents near to.
|
170
|
+
# @param _options [Hash] Optional hash for future extensions (currently unused).
|
171
|
+
#
|
172
|
+
# @return [Mongoid::Criteria] A criteria object for the query.
|
173
|
+
#
|
174
|
+
# Example:
|
175
|
+
# Bar.nearby([10, 20])
|
176
|
+
# Alarm.nearby(my_point_object)
|
177
|
+
#
|
178
|
+
def nearby(coordinates, _options = {})
|
179
|
+
if self.spatial_fields.empty?
|
180
|
+
raise "No spatial fields defined for #{self.name} to use with .nearby. " \
|
181
|
+
"Mark a field with 'spatial: true' or 'sphere: true'."
|
182
|
+
end
|
183
|
+
|
184
|
+
field_name_sym = self.spatial_fields.first.to_sym
|
185
|
+
field_definition = self.fields[field_name_sym.to_s]
|
186
|
+
|
187
|
+
unless field_definition
|
188
|
+
raise "Could not find field definition for spatial field: #{field_name_sym}"
|
189
|
+
end
|
190
|
+
|
191
|
+
query_operator = field_definition.options[:sphere] ? :near_sphere : :near
|
192
|
+
|
193
|
+
criteria.where(field_name_sym.send(query_operator) => coordinates)
|
194
|
+
end
|
120
195
|
end
|
121
196
|
end
|
122
197
|
end
|
198
|
+
|
199
|
+
require 'mongoid/geospatial/config'
|
data/mongoid-geospatial.gemspec
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../lib/mongoid/geospatial/version', __FILE__)
|
1
|
+
require File.expand_path('lib/mongoid/geospatial/version', __dir__)
|
3
2
|
|
4
3
|
Gem::Specification.new do |gem|
|
5
4
|
gem.authors = ['Ryan Ong', 'Marcos Piccinini']
|
6
5
|
gem.email = ['use@git.hub.com']
|
7
6
|
gem.summary = 'Mongoid Extension that simplifies MongoDB Geospatial Operations.'
|
8
7
|
gem.description = 'Mongoid Extension that simplifies MongoDB casting and operations on spatial Ruby objects.'
|
9
|
-
gem.homepage = 'https://github.com/
|
8
|
+
gem.homepage = 'https://github.com/mongoid/mongoid-geospatial'
|
10
9
|
|
11
10
|
gem.files = `git ls-files`.split("\n")
|
12
11
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -15,5 +14,5 @@ Gem::Specification.new do |gem|
|
|
15
14
|
gem.version = Mongoid::Geospatial::VERSION
|
16
15
|
gem.license = 'MIT'
|
17
16
|
|
18
|
-
gem.add_dependency('mongoid', ['>=
|
17
|
+
gem.add_dependency('mongoid', ['>= 4.0.0'])
|
19
18
|
end
|
data/{bench → spec}/bench
RENAMED
data/spec/models/bar.rb
CHANGED
data/spec/models/event.rb
CHANGED
@@ -10,7 +10,7 @@ class Event
|
|
10
10
|
|
11
11
|
def self.each_day(start_date, end_date)
|
12
12
|
groups = only(:date).asc(:date)
|
13
|
-
|
13
|
+
.where(:date.gte => start_date, :date.lte => end_date).group
|
14
14
|
groups.each do |hash|
|
15
15
|
yield(hash['date'], hash['group'])
|
16
16
|
end
|
data/spec/models/farm.rb
CHANGED
data/spec/models/person.rb
CHANGED
@@ -27,7 +27,7 @@ class Person
|
|
27
27
|
field :security_code
|
28
28
|
field :blood_alcohol_content, type: Float, default: -> { 0.0 }
|
29
29
|
field :last_drink_taken_at, type: Date,
|
30
|
-
|
30
|
+
default: -> { 1.day.ago.in_time_zone('Alaska') }
|
31
31
|
|
32
32
|
# Geo
|
33
33
|
field :location, type: Point
|
@@ -58,14 +58,7 @@ class Person
|
|
58
58
|
accepts_nested_attributes_for :addresses
|
59
59
|
|
60
60
|
scope :minor, -> { where(:age.lt => 18) }
|
61
|
-
scope :without_ssn, -> {
|
62
|
-
|
63
|
-
def score_with_rescoring=(score)
|
64
|
-
@rescored = score.to_i + 20
|
65
|
-
self.score_without_rescoring = score
|
66
|
-
end
|
67
|
-
|
68
|
-
alias_method_chain :score=, :rescoring
|
61
|
+
scope :without_ssn, -> { without(:ssn) }
|
69
62
|
|
70
63
|
def update_addresses
|
71
64
|
addresses.each do |address|
|
data/spec/models/river.rb
CHANGED
@@ -3,14 +3,14 @@ class River
|
|
3
3
|
include Mongoid::Document
|
4
4
|
include Mongoid::Geospatial
|
5
5
|
|
6
|
-
field :name,
|
7
|
-
field :length,
|
8
|
-
field :discharge,
|
9
|
-
field :course,
|
6
|
+
field :name, type: String
|
7
|
+
field :length, type: Integer
|
8
|
+
field :discharge, type: Integer
|
9
|
+
field :course, type: LineString, spatial: true
|
10
10
|
# set return_array to true if you do not want a hash returned all the time
|
11
|
-
field :source,
|
12
|
-
field :mouth,
|
13
|
-
field :mouth_array, type: Array,
|
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
14
|
|
15
15
|
# simplified spatial indexing
|
16
16
|
# you can only index one field in mongodb < 1.9
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::Geospatial::Config do
|
4
|
+
context 'point' do
|
5
|
+
it 'uses LonLat by default' do
|
6
|
+
expect(Mongoid::Geospatial.config.point.x).to eq Mongoid::Geospatial.lng_symbols
|
7
|
+
expect(Mongoid::Geospatial.config.point.y).to eq Mongoid::Geospatial.lat_symbols
|
8
|
+
end
|
9
|
+
context 'configured as latlon' do
|
10
|
+
before do
|
11
|
+
Mongoid::Geospatial.configure do |config|
|
12
|
+
config.point.x = Mongoid::Geospatial.lat_symbols
|
13
|
+
config.point.y = Mongoid::Geospatial.lng_symbols
|
14
|
+
end
|
15
|
+
end
|
16
|
+
it 'uses latlon' do
|
17
|
+
expect(Mongoid::Geospatial.config.point.x).to eq Mongoid::Geospatial.lat_symbols
|
18
|
+
expect(Mongoid::Geospatial.config.point.y).to eq Mongoid::Geospatial.lng_symbols
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -22,12 +22,11 @@ describe Mongoid::Geospatial::LineString do
|
|
22
22
|
expect(River.first.course).to eq([[1, 1], [9, 9], [10, 10]])
|
23
23
|
end
|
24
24
|
|
25
|
-
it 'should parent.line_string << point nicely' do
|
26
|
-
pending 'Mongoid Issue #...'
|
25
|
+
it 'should NOT parent.line_string << point nicely (mongoid doesnt track <<)' do
|
27
26
|
river = River.create!(name: 'Amazonas', course: [[1, 1], [9, 9]])
|
28
|
-
river.course
|
27
|
+
river.course << [10, 10]
|
29
28
|
river.save
|
30
|
-
expect(River.first.course).to eq([[1, 1], [9, 9]
|
29
|
+
expect(River.first.course).to eq([[1, 1], [9, 9]])
|
31
30
|
end
|
32
31
|
|
33
32
|
it 'should have same obj id' do
|
@@ -33,6 +33,46 @@ describe Mongoid::Geospatial::Point do
|
|
33
33
|
bar.location = '2.99 , 3.99'
|
34
34
|
expect(bar.location.mongoize).to eq([2.99, 3.99])
|
35
35
|
end
|
36
|
+
|
37
|
+
it 'should set point from hash' do
|
38
|
+
bar.location = { latitude: 2.99, longitude: 3.99 }
|
39
|
+
expect(bar.location.mongoize).to eq([3.99, 2.99])
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'configured as latlon' do
|
43
|
+
before do
|
44
|
+
Mongoid::Geospatial.configure do |config|
|
45
|
+
config.point.x = Mongoid::Geospatial.lat_symbols
|
46
|
+
config.point.y = Mongoid::Geospatial.lng_symbols
|
47
|
+
end
|
48
|
+
end
|
49
|
+
it 'should set point from hash' do
|
50
|
+
bar.location = { latitude: 2.99, longitude: 3.99 }
|
51
|
+
expect(bar.location.mongoize).to eq([2.99, 3.99])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have a to_s method" do
|
57
|
+
bar = Bar.create!(name: "Moe's", location: [1, 2])
|
58
|
+
expect(bar.location.to_s).to eq('1.0, 2.0')
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should have a to_s method" do
|
62
|
+
bar = Bar.create!(name: "Moe's", location: [1.0009, 21.009])
|
63
|
+
expect(bar.location.to_s).to eq('1.0009, 21.009')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should have a to_geo_json method" do
|
67
|
+
bar = Bar.create!(name: "Moe's", location: [1.0009, 21.009])
|
68
|
+
expect(bar.location.to_geo_json).to eq({
|
69
|
+
type: "Point", coordinates: [1.0009, 21.009]
|
70
|
+
})
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have a to_json method" do
|
74
|
+
bar = Bar.create!(name: "Moe's", location: [1.0009, 21.009])
|
75
|
+
expect(bar.location.to_json).to eq("[1.0009,21.009]")
|
36
76
|
end
|
37
77
|
|
38
78
|
it 'should have #reverse to get lat, lon' do
|
@@ -83,7 +123,7 @@ describe Mongoid::Geospatial::Point do
|
|
83
123
|
end
|
84
124
|
|
85
125
|
it 'should have an ActiveModel symbol accessor' do
|
86
|
-
expect(bar[:location]).to eq([3, 2])
|
126
|
+
expect(bar[:location].to_a).to eq([3, 2])
|
87
127
|
end
|
88
128
|
|
89
129
|
it 'should have a radius helper' do
|
@@ -129,7 +169,12 @@ describe Mongoid::Geospatial::Point do
|
|
129
169
|
end
|
130
170
|
|
131
171
|
it 'returns the documents sorted closest to furthest' do
|
132
|
-
expect(Bar.
|
172
|
+
expect(Bar.closest_to_location(jim.location).to_a)
|
173
|
+
.to eq([paris, prague, berlin])
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns the documents sorted closest to furthest' do
|
177
|
+
expect(Bar.where(:location.near => jim.location).to_a)
|
133
178
|
.to eq([paris, prague, berlin])
|
134
179
|
end
|
135
180
|
|
@@ -198,7 +243,8 @@ describe Mongoid::Geospatial::Point do
|
|
198
243
|
it 'returns the documents within a box' do
|
199
244
|
poly = Mongoid::Geospatial::LineString.new(
|
200
245
|
[elvis.location.map { |c| c + 1 },
|
201
|
-
elvis.location.map { |c| c - 1 }]
|
246
|
+
elvis.location.map { |c| c - 1 }]
|
247
|
+
)
|
202
248
|
expect(Bar.where(:location.within_polygon => [poly.geom_box]).to_a)
|
203
249
|
.to include(mile3)
|
204
250
|
end
|
@@ -239,7 +285,7 @@ describe Mongoid::Geospatial::Point do
|
|
239
285
|
|
240
286
|
describe 'with rgeo' do
|
241
287
|
describe 'instantiated' do
|
242
|
-
let(:bar) { Bar.
|
288
|
+
let(:bar) { Bar.new(name: 'Vitinho', location: [10, 10]) }
|
243
289
|
|
244
290
|
it 'should demongoize to rgeo' do
|
245
291
|
expect(bar.location.class).to eql(Mongoid::Geospatial::Point)
|
@@ -49,20 +49,20 @@ describe Mongoid::Geospatial::Polygon do
|
|
49
49
|
Farm.create_indexes
|
50
50
|
end
|
51
51
|
|
52
|
-
let
|
52
|
+
let(:ranch) do
|
53
53
|
Farm.create!(name: 'Ranch',
|
54
54
|
area: [[1, 1], [3, 3], [3, 1], [1, 1]],
|
55
55
|
geom: [2, 2])
|
56
56
|
end
|
57
57
|
|
58
|
-
let
|
58
|
+
let(:farm) do
|
59
59
|
Farm.create!(name: 'Farm',
|
60
60
|
area: [[47, 1], [48, 1.5], [49, 3], [49, 1], [47, 1]],
|
61
61
|
geom: [48, 1.28])
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'returns the documents within a box' do
|
65
|
-
query = Farm.
|
65
|
+
query = Farm.geo_spatial(:geom.within_polygon => [ranch.area])
|
66
66
|
expect(query.to_a).to eq([ranch])
|
67
67
|
end
|
68
68
|
|