geocoder 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of geocoder might be problematic. Click here for more details.
- data/.gitignore +3 -0
- data/CHANGELOG.rdoc +19 -4
- data/README.rdoc +115 -76
- data/Rakefile +2 -33
- data/VERSION +1 -0
- data/lib/geocoder.rb +78 -5
- data/lib/geocoder/configuration.rb +11 -3
- data/lib/geocoder/lookups/base.rb +110 -0
- data/lib/geocoder/lookups/freegeoip.rb +40 -0
- data/lib/geocoder/lookups/google.rb +31 -0
- data/lib/geocoder/lookups/yahoo.rb +29 -0
- data/lib/geocoder/{active_record.rb → orms/active_record.rb} +27 -82
- data/lib/geocoder/orms/active_record_legacy.rb +58 -0
- data/lib/geocoder/orms/base.rb +96 -0
- data/lib/geocoder/railtie.rb +50 -38
- data/lib/geocoder/request.rb +17 -0
- data/lib/geocoder/results/base.rb +58 -0
- data/lib/geocoder/results/freegeoip.rb +37 -0
- data/lib/geocoder/{result.rb → results/google.rb} +26 -8
- data/lib/geocoder/results/yahoo.rb +40 -0
- data/lib/tasks/geocoder.rake +1 -1
- data/test/fixtures/freegeoip_74_200_247_59.json +12 -0
- data/test/fixtures/google_garbage.json +456 -0
- data/test/fixtures/google_madison_square_garden.json +57 -0
- data/test/fixtures/google_no_results.json +4 -0
- data/test/fixtures/yahoo_garbage.json +50 -0
- data/test/fixtures/yahoo_madison_square_garden.json +46 -0
- data/test/fixtures/yahoo_no_results.json +10 -0
- data/test/geocoder_test.rb +185 -12
- data/test/test_helper.rb +84 -17
- metadata +50 -17
- data/lib/geocoder/lookup.rb +0 -90
@@ -1,8 +1,16 @@
|
|
1
1
|
module Geocoder
|
2
2
|
class Configuration
|
3
|
-
|
3
|
+
def self.timeout; @@timeout; end
|
4
|
+
def self.timeout=(obj); @@timeout = obj; end
|
5
|
+
|
6
|
+
def self.lookup; @@lookup; end
|
7
|
+
def self.lookup=(obj); @@lookup = obj; end
|
8
|
+
|
9
|
+
def self.yahoo_appid; @@yahoo_appid; end
|
10
|
+
def self.yahoo_appid=(obj); @@yahoo_appid = obj; end
|
4
11
|
end
|
5
12
|
end
|
6
13
|
|
7
|
-
Geocoder::Configuration.timeout
|
8
|
-
|
14
|
+
Geocoder::Configuration.timeout = 3
|
15
|
+
Geocoder::Configuration.lookup = :google
|
16
|
+
Geocoder::Configuration.yahoo_appid = ""
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
unless defined? ActiveSupport::JSON
|
3
|
+
begin
|
4
|
+
require 'json'
|
5
|
+
rescue LoadError
|
6
|
+
raise LoadError, "Please install the json gem to parse geocoder results."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Geocoder
|
11
|
+
module Lookup
|
12
|
+
class Base
|
13
|
+
|
14
|
+
##
|
15
|
+
# Query the geocoding API and return a Geocoder::Result object.
|
16
|
+
# Returns +nil+ on timeout or error.
|
17
|
+
#
|
18
|
+
# Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS",
|
19
|
+
# "205.128.54.202") for geocoding, or coordinates (latitude, longitude)
|
20
|
+
# for reverse geocoding.
|
21
|
+
#
|
22
|
+
def search(*args)
|
23
|
+
if res = result(args.join(","), args.size == 2)
|
24
|
+
result_class.new(res)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private # -------------------------------------------------------------
|
30
|
+
|
31
|
+
##
|
32
|
+
# Geocoder::Result object or nil on timeout or other error.
|
33
|
+
#
|
34
|
+
def result(query, reverse = false)
|
35
|
+
fail
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# URL to use for querying the geocoding engine.
|
40
|
+
#
|
41
|
+
def query_url(query, reverse = false)
|
42
|
+
fail
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Class of the result objects
|
47
|
+
#
|
48
|
+
def result_class
|
49
|
+
eval("Geocoder::Result::#{self.class.to_s.split(":").last}")
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Returns a parsed search result (Ruby hash).
|
54
|
+
#
|
55
|
+
def fetch_data(query, reverse = false)
|
56
|
+
begin
|
57
|
+
parse_raw_data fetch_raw_data(query, reverse)
|
58
|
+
rescue SocketError
|
59
|
+
warn "Geocoding API connection cannot be established."
|
60
|
+
rescue TimeoutError
|
61
|
+
warn "Geocoding API not responding fast enough " +
|
62
|
+
"(see Geocoder::Configuration.timeout to set limit)."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Parses a raw search result (returns hash or array).
|
68
|
+
#
|
69
|
+
def parse_raw_data(raw_data)
|
70
|
+
if defined?(JSON) and defined?(JSON.parse)
|
71
|
+
begin
|
72
|
+
JSON.parse(raw_data)
|
73
|
+
rescue
|
74
|
+
warn "Geocoding API's response was not valid JSON."
|
75
|
+
end
|
76
|
+
elsif defined?(ActiveSupport::JSON)
|
77
|
+
ActiveSupport::JSON.decode(raw_data)
|
78
|
+
else
|
79
|
+
raise Geocoder::Error, "No JSON-parsing library found. " +
|
80
|
+
"Please install either the 'json' or 'activesupport' gem."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Fetches a raw search result (JSON string).
|
86
|
+
#
|
87
|
+
def fetch_raw_data(query, reverse = false)
|
88
|
+
url = query_url(query, reverse)
|
89
|
+
timeout(Geocoder::Configuration.timeout) do
|
90
|
+
Net::HTTP.get_response(URI.parse(url)).body
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Is the given string a loopback IP address?
|
96
|
+
#
|
97
|
+
def loopback_address?(ip)
|
98
|
+
!!(ip == "0.0.0.0" or ip.match(/^127/))
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Simulate ActiveSupport's Object#to_query.
|
103
|
+
#
|
104
|
+
def hash_to_query(hash)
|
105
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
|
106
|
+
hash.collect{ |p| p.map{ |i| CGI.escape i.to_s } * '=' }.sort * '&'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/freegeoip'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Freegeoip < Base
|
6
|
+
|
7
|
+
private # ---------------------------------------------------------------
|
8
|
+
|
9
|
+
def result(query, reverse = false)
|
10
|
+
# don't look up a loopback address, just return the stored result
|
11
|
+
return reserved_result(query) if loopback_address?(query)
|
12
|
+
begin
|
13
|
+
if doc = fetch_data(query, reverse)
|
14
|
+
doc
|
15
|
+
end
|
16
|
+
rescue StandardError # Freegeoip.net returns HTML on bad request
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def reserved_result(ip)
|
22
|
+
{
|
23
|
+
"ip" => ip,
|
24
|
+
"city" => "",
|
25
|
+
"region_code" => "",
|
26
|
+
"region_name" => "",
|
27
|
+
"metrocode" => "",
|
28
|
+
"zipcode" => "",
|
29
|
+
"latitude" => "0",
|
30
|
+
"longitude" => "0",
|
31
|
+
"country_name" => "Reserved",
|
32
|
+
"country_code" => "RD"
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def query_url(query, reverse = false)
|
37
|
+
"http://freegeoip.net/json/#{query}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/google"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Google < Base
|
6
|
+
|
7
|
+
private # ---------------------------------------------------------------
|
8
|
+
|
9
|
+
def result(query, reverse = false)
|
10
|
+
doc = fetch_data(query, reverse)
|
11
|
+
case doc['status']; when "OK" # OK status implies >0 results
|
12
|
+
doc['results'].first
|
13
|
+
when "OVER_QUERY_LIMIT"
|
14
|
+
warn "Google Geocoding API error: over query limit."
|
15
|
+
when "REQUEST_DENIED"
|
16
|
+
warn "Google Geocoding API error: request denied."
|
17
|
+
when "INVALID_REQUEST"
|
18
|
+
warn "Google Geocoding API error: invalid request."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def query_url(query, reverse = false)
|
23
|
+
params = {
|
24
|
+
(reverse ? :latlng : :address) => query,
|
25
|
+
:sensor => "false"
|
26
|
+
}
|
27
|
+
"http://maps.google.com/maps/api/geocode/json?" + hash_to_query(params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/yahoo"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Yahoo < Base
|
6
|
+
|
7
|
+
private # ---------------------------------------------------------------
|
8
|
+
|
9
|
+
def result(query, reverse = false)
|
10
|
+
doc = fetch_data(query, reverse)
|
11
|
+
if doc = doc['ResultSet'] and doc['Error'] == 0
|
12
|
+
doc['Results'].first if doc['Found'] > 0
|
13
|
+
else
|
14
|
+
warn "Yahoo Geocoding API error: #{doc['Error']} (#{doc['ErrorMessage']})."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def query_url(query, reverse = false)
|
19
|
+
params = {
|
20
|
+
:location => query,
|
21
|
+
:flags => "JXTSR",
|
22
|
+
:gflags => "AC#{'R' if reverse}",
|
23
|
+
:appid => Geocoder::Configuration.yahoo_appid
|
24
|
+
}
|
25
|
+
"http://where.yahooapis.com/geocode?" + hash_to_query(params)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -1,8 +1,13 @@
|
|
1
|
+
require 'geocoder/orms/base'
|
2
|
+
require 'geocoder/orms/active_record_legacy'
|
3
|
+
|
1
4
|
##
|
2
5
|
# Add geocoding functionality to any ActiveRecord object.
|
3
6
|
#
|
4
|
-
module Geocoder
|
7
|
+
module Geocoder::Orm
|
5
8
|
module ActiveRecord
|
9
|
+
include Base
|
10
|
+
include ActiveRecord::Legacy
|
6
11
|
|
7
12
|
##
|
8
13
|
# Implementation of 'included' hook method.
|
@@ -28,7 +33,7 @@ module Geocoder
|
|
28
33
|
#
|
29
34
|
scope :near, lambda{ |location, *args|
|
30
35
|
latitude, longitude = location.is_a?(Array) ?
|
31
|
-
location : Geocoder
|
36
|
+
location : Geocoder.coordinates(location)
|
32
37
|
if latitude and longitude
|
33
38
|
near_scope_options(latitude, longitude, *args)
|
34
39
|
else
|
@@ -112,7 +117,7 @@ module Geocoder
|
|
112
117
|
["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
|
113
118
|
coordinate_bounds(latitude, longitude, radius)
|
114
119
|
if obj = options[:exclude]
|
115
|
-
conditions[0] << " AND id != ?"
|
120
|
+
conditions[0] << " AND #{table_name}.id != ?"
|
116
121
|
conditions << obj.id
|
117
122
|
end
|
118
123
|
{
|
@@ -142,94 +147,34 @@ module Geocoder
|
|
142
147
|
end
|
143
148
|
|
144
149
|
##
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
def read_coordinates
|
149
|
-
[:latitude, :longitude].map{ |i| send self.class.geocoder_options[i] }
|
150
|
-
end
|
151
|
-
|
152
|
-
##
|
153
|
-
# Is this object geocoded? (Does it have latitude and longitude?)
|
154
|
-
#
|
155
|
-
def geocoded?
|
156
|
-
read_coordinates.compact.size > 0
|
157
|
-
end
|
158
|
-
|
159
|
-
##
|
160
|
-
# Calculate the distance from the object to a point (lat,lon).
|
161
|
-
#
|
162
|
-
# <tt>:units</tt> :: <tt>:mi</tt> (default) or <tt>:km</tt>
|
163
|
-
#
|
164
|
-
def distance_to(lat, lon, units = :mi)
|
165
|
-
return nil unless geocoded?
|
166
|
-
mylat,mylon = read_coordinates
|
167
|
-
Geocoder::Calculations.distance_between(mylat, mylon, lat, lon, :units => units)
|
168
|
-
end
|
169
|
-
|
170
|
-
##
|
171
|
-
# Get other geocoded objects within a given radius.
|
172
|
-
#
|
173
|
-
# <tt>:units</tt> :: <tt>:mi</tt> (default) or <tt>:km</tt>
|
150
|
+
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
|
151
|
+
# (or other as specified in +geocoded_by+). Returns coordinates (array).
|
174
152
|
#
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
# Fetch coordinates and assign +latitude+ and +longitude+. Also returns
|
183
|
-
# coordinates as an array: <tt>[lat, lon]</tt>.
|
184
|
-
#
|
185
|
-
def fetch_coordinates(save = false)
|
186
|
-
address_method = self.class.geocoder_options[:user_address]
|
187
|
-
unless address_method.is_a? Symbol
|
188
|
-
raise Geocoder::ConfigurationError,
|
189
|
-
"You are attempting to fetch coordinates but have not specified " +
|
190
|
-
"a method which provides an address for the object."
|
191
|
-
end
|
192
|
-
coords = Geocoder::Lookup.coordinates(send(address_method))
|
193
|
-
unless coords.blank?
|
194
|
-
method = (save ? "update" : "write") + "_attribute"
|
195
|
-
send method, self.class.geocoder_options[:latitude], coords[0]
|
196
|
-
send method, self.class.geocoder_options[:longitude], coords[1]
|
153
|
+
def geocode
|
154
|
+
do_lookup(false) do |o,r|
|
155
|
+
unless r.latitude.nil? or r.longitude.nil?
|
156
|
+
o.send :write_attribute, self.class.geocoder_options[:latitude], r.latitude
|
157
|
+
o.send :write_attribute, self.class.geocoder_options[:longitude], r.longitude
|
158
|
+
end
|
159
|
+
r.coordinates
|
197
160
|
end
|
198
|
-
coords
|
199
161
|
end
|
200
162
|
|
201
|
-
|
202
|
-
# Fetch coordinates and update (save) +latitude+ and +longitude+ data.
|
203
|
-
#
|
204
|
-
def fetch_coordinates!
|
205
|
-
fetch_coordinates(true)
|
206
|
-
end
|
163
|
+
#alias_method :fetch_coordinates, :geocode
|
207
164
|
|
208
165
|
##
|
209
|
-
#
|
210
|
-
#
|
166
|
+
# Look up address and assign to +address+ attribute (or other as specified
|
167
|
+
# in +reverse_geocoded_by+). Returns address (string).
|
211
168
|
#
|
212
|
-
def
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
"attributes which provide coordinates for the object."
|
219
|
-
end
|
220
|
-
address = Geocoder::Lookup.address(send(lat_attr), send(lon_attr))
|
221
|
-
unless address.blank?
|
222
|
-
method = (save ? "update" : "write") + "_attribute"
|
223
|
-
send method, self.class.geocoder_options[:fetched_address], address
|
169
|
+
def reverse_geocode
|
170
|
+
do_lookup(true) do |o,r|
|
171
|
+
unless r.address.nil?
|
172
|
+
o.send :write_attribute, self.class.geocoder_options[:fetched_address], r.address
|
173
|
+
end
|
174
|
+
r.address
|
224
175
|
end
|
225
|
-
address
|
226
176
|
end
|
227
177
|
|
228
|
-
|
229
|
-
# Fetch address and update (save) +address+ data.
|
230
|
-
#
|
231
|
-
def fetch_address!
|
232
|
-
fetch_address(true)
|
233
|
-
end
|
178
|
+
#alias_method :fetch_address, :reverse_geocode
|
234
179
|
end
|
235
180
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Geocoder::Orm::ActiveRecord
|
2
|
+
module Legacy
|
3
|
+
|
4
|
+
##
|
5
|
+
# Fetch coordinates and update (save) +latitude+ and +longitude+ data.
|
6
|
+
#
|
7
|
+
def fetch_coordinates!
|
8
|
+
warn "DEPRECATION WARNING: The 'fetch_coordinates!' method is deprecated and will be removed in geocoder v1.0. " +
|
9
|
+
"Please use 'geocode' instead and then save your objects manually."
|
10
|
+
do_lookup(false) do |o,r|
|
11
|
+
unless r.latitude.nil? or r.longitude.nil?
|
12
|
+
o.send :update_attribute, self.class.geocoder_options[:latitude], r.latitude
|
13
|
+
o.send :update_attribute, self.class.geocoder_options[:longitude], r.longitude
|
14
|
+
end
|
15
|
+
r.coordinates
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch_coordinates(*args)
|
20
|
+
warn "DEPRECATION WARNING: The 'fetch_coordinates' method will cease taking " +
|
21
|
+
"an argument in geocoder v1.0. Please save your objects manually." if args.size > 0
|
22
|
+
do_lookup(false) do |o,r|
|
23
|
+
unless r.latitude.nil? or r.longitude.nil?
|
24
|
+
method = ((args.size > 0 && args.first) ? "update" : "write" ) + "_attribute"
|
25
|
+
o.send method, self.class.geocoder_options[:latitude], r.latitude
|
26
|
+
o.send method, self.class.geocoder_options[:longitude], r.longitude
|
27
|
+
end
|
28
|
+
r.coordinates
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Fetch address and update (save) +address+ data.
|
34
|
+
#
|
35
|
+
def fetch_address!
|
36
|
+
warn "DEPRECATION WARNING: The 'fetch_address!' method is deprecated and will be removed in geocoder v1.0. " +
|
37
|
+
"Please use 'reverse_geocode' instead and then save your objects manually."
|
38
|
+
do_lookup(true) do |o,r|
|
39
|
+
unless r.address.nil?
|
40
|
+
o.send :update_attribute, self.class.geocoder_options[:fetched_address], r.address
|
41
|
+
end
|
42
|
+
r.address
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_address(*args)
|
47
|
+
warn "DEPRECATION WARNING: The 'fetch_address' method will cease taking " +
|
48
|
+
"an argument in geocoder v1.0. Please save your objects manually." if args.size > 0
|
49
|
+
do_lookup(true) do |o,r|
|
50
|
+
unless r.latitude.nil? or r.longitude.nil?
|
51
|
+
method = ((args.size > 0 && args.first) ? "update" : "write" ) + "_attribute"
|
52
|
+
o.send method, self.class.geocoder_options[:fetched_address], r.address
|
53
|
+
end
|
54
|
+
r.address
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Geocoder
|
2
|
+
module Orm
|
3
|
+
module Base
|
4
|
+
|
5
|
+
##
|
6
|
+
# Is this object geocoded? (Does it have latitude and longitude?)
|
7
|
+
#
|
8
|
+
def geocoded?
|
9
|
+
read_coordinates.compact.size > 0
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Calculate the distance from the object to an arbitrary point.
|
14
|
+
# Takes two floats (latitude, longitude) and a symbol specifying the
|
15
|
+
# units to be used (:mi or :km; default is :mi).
|
16
|
+
#
|
17
|
+
def distance_to(lat, lon, units = :mi)
|
18
|
+
return nil unless geocoded?
|
19
|
+
mylat,mylon = read_coordinates
|
20
|
+
Geocoder::Calculations.distance_between(mylat, mylon, lat, lon, :units => units)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :distance_from, :distance_to
|
24
|
+
|
25
|
+
##
|
26
|
+
# Get nearby geocoded objects. Takes a radius (integer) and a symbol
|
27
|
+
# representing the units of the ratius (:mi or :km; default is :mi).
|
28
|
+
#
|
29
|
+
def nearbys(radius = 20, units = :mi)
|
30
|
+
return [] unless geocoded?
|
31
|
+
options = {:exclude => self, :units => units}
|
32
|
+
self.class.near(read_coordinates, radius, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
|
37
|
+
# (or other as specified in +geocoded_by+). Returns coordinates (array).
|
38
|
+
#
|
39
|
+
def geocode
|
40
|
+
fail
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Look up address and assign to +address+ attribute (or other as specified
|
45
|
+
# in +reverse_geocoded_by+). Returns address (string).
|
46
|
+
#
|
47
|
+
def reverse_geocode
|
48
|
+
fail
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
private # --------------------------------------------------------------
|
53
|
+
|
54
|
+
##
|
55
|
+
# Look up geographic data based on object attributes (configured in
|
56
|
+
# geocoded_by or reverse_geocoded_by) and handle the result with the
|
57
|
+
# block (given to geocoded_by or reverse_geocoded_by). The block is
|
58
|
+
# given two-arguments: the object being geocoded and a
|
59
|
+
# Geocoder::Result object with the geocoding results).
|
60
|
+
#
|
61
|
+
def do_lookup(reverse = false)
|
62
|
+
options = self.class.geocoder_options
|
63
|
+
if reverse and options[:reverse_geocode]
|
64
|
+
args = [:latitude, :longitude]
|
65
|
+
elsif !reverse and options[:geocode]
|
66
|
+
args = [:user_address]
|
67
|
+
else
|
68
|
+
return
|
69
|
+
end
|
70
|
+
args.map!{ |a| send(options[a]) }
|
71
|
+
|
72
|
+
if result = Geocoder.search(*args)
|
73
|
+
|
74
|
+
# execute custom block, if specified in configuration
|
75
|
+
block_key = reverse ? :reverse_block : :geocode_block
|
76
|
+
if custom_block = options[block_key]
|
77
|
+
custom_block.call(self, result)
|
78
|
+
|
79
|
+
# else execute block passed directly to this method,
|
80
|
+
# which generally performs the "auto-assigns"
|
81
|
+
elsif block_given?
|
82
|
+
yield(self, result)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Read the coordinates [lat,lon] of the object.
|
89
|
+
# Looks at user config to determine attributes.
|
90
|
+
#
|
91
|
+
def read_coordinates
|
92
|
+
[:latitude, :longitude].map{ |i| send self.class.geocoder_options[i] }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|