forked from alexreisner/geocoder
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mongo_base.rb
83 lines (70 loc) · 2.47 KB
/
mongo_base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module Geocoder::Store
module MongoBase
def self.included_by_model(base)
base.class_eval do
scope :geocoded, lambda {
where(geocoder_options[:coordinates].ne => nil)
}
scope :not_geocoded, lambda {
where(geocoder_options[:coordinates] => nil)
}
scope :near, lambda{ |location, *args|
coords = Geocoder::Calculations.extract_coordinates(location)
# no results if no lat/lon given
return where(:id => false) unless coords.is_a?(Array)
radius = args.size > 0 ? args.shift : 20
options = args.size > 0 ? args.shift : {}
options[:units] ||= geocoder_options[:units]
# Use BSON::OrderedHash if Ruby's hashes are unordered.
# Conditions must be in order required by indexes (see mongo gem).
empty = RUBY_VERSION.split('.')[1].to_i < 9 ? BSON::OrderedHash.new : {}
conds = empty.clone
field = geocoder_options[:coordinates]
conds[field] = empty.clone
conds[field]["$nearSphere"] = coords.reverse
conds[field]["$maxDistance"] = \
Geocoder::Calculations.distance_to_radians(radius, options[:units])
if obj = options[:exclude]
conds[:_id.ne] = obj.id
end
where(conds)
}
end
end
##
# Coordinates [lat,lon] of the object.
# This method always returns coordinates in lat,lon order,
# even though internally they are stored in the opposite order.
#
def to_coordinates
coords = send(self.class.geocoder_options[:coordinates])
coords.is_a?(Array) ? coords.reverse : []
end
##
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
# (or other as specified in +geocoded_by+). Returns coordinates (array).
#
def geocode
do_lookup(false) do |o,rs|
r = rs.first
unless r.coordinates.nil?
o.send :write_attribute, self.class.geocoder_options[:coordinates], r.coordinates.reverse
end
r.coordinates
end
end
##
# Look up address and assign to +address+ attribute (or other as specified
# in +reverse_geocoded_by+). Returns address (string).
#
def reverse_geocode
do_lookup(true) do |o,rs|
r = rs.first
unless r.address.nil?
o.send :write_attribute, self.class.geocoder_options[:fetched_address], r.address
end
r.address
end
end
end
end