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.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +8 -0
  3. data/.travis.yml +26 -20
  4. data/CHANGELOG.md +23 -0
  5. data/CONTRIBUTING.md +118 -0
  6. data/Gemfile +8 -16
  7. data/Guardfile +2 -2
  8. data/MIT-LICENSE +2 -2
  9. data/README.md +202 -212
  10. data/RELEASING.md +62 -0
  11. data/Rakefile +4 -1
  12. data/lib/mongoid/geospatial/config/point.rb +19 -0
  13. data/lib/mongoid/geospatial/config.rb +29 -0
  14. data/lib/mongoid/geospatial/fields/circle.rb +3 -3
  15. data/lib/mongoid/geospatial/fields/point.rb +29 -10
  16. data/lib/mongoid/geospatial/geometry_field.rb +6 -4
  17. data/lib/mongoid/geospatial/helpers/sphere.rb +1 -1
  18. data/lib/mongoid/geospatial/version.rb +1 -1
  19. data/lib/mongoid/geospatial/wrappers/georuby.rb +1 -0
  20. data/lib/mongoid/geospatial.rb +107 -30
  21. data/mongoid-geospatial.gemspec +3 -4
  22. data/{bench → spec}/bench +1 -1
  23. data/spec/models/bar.rb +1 -0
  24. data/spec/models/event.rb +1 -1
  25. data/spec/models/farm.rb +1 -1
  26. data/spec/models/person.rb +2 -9
  27. data/spec/models/river.rb +7 -7
  28. data/spec/mongoid/geospatial/config_spec.rb +22 -0
  29. data/spec/mongoid/geospatial/fields/line_string_spec.rb +3 -4
  30. data/spec/mongoid/geospatial/fields/point_spec.rb +50 -4
  31. data/spec/mongoid/geospatial/fields/polygon_spec.rb +3 -3
  32. data/spec/mongoid/geospatial/geospatial_spec.rb +80 -8
  33. data/spec/mongoid/geospatial/helpers/core_spec.rb +6 -3
  34. data/spec/mongoid/geospatial/helpers/spatial_spec.rb +3 -3
  35. data/spec/mongoid/geospatial/helpers/sphere_spec.rb +6 -6
  36. data/spec/mongoid.yml +298 -0
  37. data/spec/spec_helper.rb +9 -19
  38. data/spec/support/authentication.rb +0 -1
  39. 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
@@ -5,10 +5,10 @@ module Mongoid
5
5
  class Circle < GeometryField
6
6
  attr_accessor :center, :radius
7
7
 
8
- def point
9
- Point.new(self[0])
8
+ def center
9
+ Point.new(*self[0])
10
10
  end
11
- alias_method :point, :center
11
+ alias point center
12
12
 
13
13
  def radius
14
14
  self[1]
@@ -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
- alias_method :to_a, :mongoize
24
- alias_method :to_xy, :mongoize
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
- alias_method :to_hash, :to_hsh
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
- fail 'Invalid Point'
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
- fail 'Hash must have at least 2 items' if hsh.size < 2
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.lat_symbols & hsh.keys).first
228
+ v = (Mongoid::Geospatial::Config::Point.y & hsh.keys).first
212
229
  return hsh[v].to_f if !v.nil? && hsh[v]
213
- fail "Hash must contain #{Mongoid::Geospatial.lat_symbols.inspect}"
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.lng_symbols & hsh.keys).first
235
+ v = (Mongoid::Geospatial::Config::Point.x & hsh.keys).first
218
236
  return hsh[v].to_f if !v.nil? && hsh[v]
219
- fail "Hash must contain #{Mongoid::Geospatial.lng_symbols.inspect}"
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, min_x = -Float::MAX, Float::MAX
21
- max_y, min_y = -Float::MAX, Float::MAX
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
- alias_method :bbox, :bounding_box
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
- alias_method :center, :center_point
58
+ alias center center_point
57
59
 
58
60
  #
59
61
  # Generates a radius from the point
@@ -11,6 +11,6 @@ Mongoid::Fields.option :sphere do |model, field, _options|
11
11
  spatial_fields_indexed << field.name.to_sym
12
12
 
13
13
  # Create 2Dsphere index
14
- sphere_index field.name
14
+ spherical_index field.name
15
15
  end
16
16
  end
@@ -1,6 +1,6 @@
1
1
  module Mongoid
2
2
  # Mongoid Geospatial version
3
3
  module Geospatial
4
- VERSION = '5.0.0'
4
+ VERSION = '7.0.0'.freeze
5
5
  end
6
6
  end
@@ -16,6 +16,7 @@ module Mongoid
16
16
  # @return (GeoRuby::SimpleFeatures::Point)
17
17
  def to_geo
18
18
  return unless valid?
19
+
19
20
  GeoRuby::SimpleFeatures::Point.xy(x, y)
20
21
  end
21
22
 
@@ -1,6 +1,5 @@
1
1
  require 'mongoid'
2
- # require 'active_support/core_ext/string/inflections'
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: EARTH_RADIUS_KM * 1000,
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
- # Create Spatial index for given field
73
+ # Creates a 2d spatial index for the given field.
76
74
  #
77
- #
78
- # @param [String,Symbol] name
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 Sphere index for given field
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] options options for spatial_index
86
+ # @param name [String, Symbol] The name of the field to index.
87
+ # @param options [Hash] Additional options for the index.
95
88
  #
96
- # http://www.mongodb.org/display/DOCS/Geospatial+Indexing
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
- # Creates Sphere index for given field
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
- # @param [String,Symbol] name
108
- # @param [Hash] options options for spatial_index
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
- # http://www.mongodb.org/display/DOCS/Geospatial+Indexing
111
- # #GeospatialIndexing-geoNearCommand
112
- def spatial_scope(field, _opts = {})
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
- # define_method(:close) do |args|
115
- define_method(:nearby) do |args|
116
- queryable.where(field.near_sphere => args)
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'
@@ -1,12 +1,11 @@
1
- # -*- encoding: utf-8 -*-
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/nofxx/mongoid-geospatial'
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', ['>= 5.0.0.beta'])
17
+ gem.add_dependency('mongoid', ['>= 4.0.0'])
19
18
  end
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Just for fun
4
4
  #
5
- $LOAD_PATH << File.expand_path('../../lib', __FILE__)
5
+ $LOAD_PATH << File.expand_path('../lib', __dir__)
6
6
 
7
7
  require 'mongoid/geospatial'
8
8
 
data/spec/models/bar.rb CHANGED
@@ -9,5 +9,6 @@ class Bar
9
9
 
10
10
  has_one :rating, as: :ratable
11
11
 
12
+ spherical_index :location
12
13
  spatial_scope :location
13
14
  end
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
- .where(:date.gte => start_date, :date.lte => end_date).group
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
@@ -6,7 +6,7 @@ class Farm
6
6
  field :name, type: String
7
7
  field :geom, type: Point, sphere: true
8
8
  field :area, type: Polygon, spatial: true
9
- field :m2, type: Fixnum
9
+ field :m2, type: Integer
10
10
 
11
11
  spatial_index :geom
12
12
  spatial_index :area
@@ -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
- default: -> { 1.day.ago.in_time_zone('Alaska') }
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, -> { 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, type: String
7
- field :length, type: Integer
8
- field :discharge, type: Integer
9
- field :course, type: LineString, spatial: true
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, type: Point, spatial: true
12
- field :mouth, type: Point, spatial: { lat: 'latitude', lng: 'longitude' }
13
- field :mouth_array, type: Array, spatial: { return_array: true }
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.push [10, 10]
27
+ river.course << [10, 10]
29
28
  river.save
30
- expect(River.first.course).to eq([[1, 1], [9, 9], [10, 10]])
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.where(:location.near => jim.location))
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.create!(name: 'Vitinho', location: [10, 10]) }
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!(:ranch) do
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!(:farm) do
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.geo_spacial(:geom.within_polygon => [ranch.area])
65
+ query = Farm.geo_spatial(:geom.within_polygon => [ranch.area])
66
66
  expect(query.to_a).to eq([ranch])
67
67
  end
68
68