Skip to content

Commit cc5fd43

Browse files
authored
Merge pull request #139 from SenteraLLC/dpa-in-bounds-inclusive-option
Enhanced ActsAsMappable#in_bounds to allow the query to include thing…
2 parents 93b7153 + dc52dc3 commit cc5fd43

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

README.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ If you are displaying points on a map, you probably need to query for whatever f
264264
Store.in_bounds([sw_point,ne_point]).all
265265
```
266266

267+
If you want the query to return things that are located on the rectangular bounds, specify the `inclusive` option set to true:
268+
269+
```ruby
270+
Store.in_bounds([sw_point,ne_point], :inclusive => true).all
271+
```
272+
267273
The input to `bounds` can be an array with the two points or a Bounds object. However you provide them, the order should always be the southwest corner, northeast corner of the rectangle. Typically, you will be getting the sw\_point and ne\_point from a map that is displayed on a web page.
268274

269275
If you need to calculate the bounding box from a point and radius, you can do that:

lib/geokit-rails/acts_as_mappable.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,12 @@ def in_range(range, options = {})
141141
end
142142

143143
def in_bounds(bounds, options = {})
144+
inclusive = options.delete(:inclusive) || false
144145
options[:bounds] = bounds
145146
#geo_scope(options)
146147
#where(distance_conditions(options))
147148
bounds = extract_bounds_from_options(options)
148-
where(bound_conditions(bounds))
149+
where(bound_conditions(bounds, inclusive))
149150
end
150151

151152
def by_distance(options = {})
@@ -263,15 +264,22 @@ def distance_conditions(options)
263264
end
264265
end
265266

266-
def bound_conditions(bounds)
267+
def bound_conditions(bounds, inclusive = false)
267268
return nil unless bounds
269+
if inclusive
270+
lt_operator = :lteq
271+
gt_operator = :gteq
272+
else
273+
lt_operator = :lt
274+
gt_operator = :gt
275+
end
268276
sw,ne = bounds.sw, bounds.ne
269277
lat, lng = Arel.sql(qualified_lat_column_name), Arel.sql(qualified_lng_column_name)
270-
lat.gt(sw.lat).and(lat.lt(ne.lat)).and(
278+
lat.send(gt_operator, sw.lat).and(lat.send(lt_operator, ne.lat)).and(
271279
if bounds.crosses_meridian?
272-
lng.lt(ne.lng).or(lng.gt(sw.lng))
280+
lng.send(lt_operator, ne.lng).or(lng.send(gt_operator, sw.lng))
273281
else
274-
lng.gt(sw.lng).and(lng.lt(ne.lng))
282+
lng.send(gt_operator, sw.lng).and(lng.send(lt_operator, ne.lng))
275283
end
276284
)
277285
end

test/acts_as_mappable_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,16 @@ def test_find_within_bounds
389389
assert_equal 2, locations.count
390390
end
391391

392+
def test_find_within_bounds_with_inclusive
393+
sw = Geokit::LatLng.new(@loc_a.lat,@loc_a.lng)
394+
ne = sw
395+
bounds = [sw,ne]
396+
locations = Location.in_bounds(bounds, :inclusive => false)
397+
assert_equal 0, locations.count
398+
locations = Location.in_bounds(bounds, :inclusive => true)
399+
assert_equal 1, locations.count
400+
end
401+
392402
def test_find_within_bounds_ordered_by_distance
393403
#locations = Location.in_bounds([@sw,@ne], :origin=>@bounds_center).order('distance asc')
394404
locations = Location.in_bounds([@sw,@ne]).by_distance(:origin => @bounds_center)

0 commit comments

Comments
 (0)