geocoder-sgonyea 1.1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +298 -0
- data/LICENSE +20 -0
- data/README.md +656 -0
- data/Rakefile +25 -0
- data/bin/geocode +5 -0
- data/examples/autoexpire_cache.rb +28 -0
- data/gemfiles/Gemfile.mongoid-2.4.x +15 -0
- data/lib/generators/geocoder/config/config_generator.rb +14 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +21 -0
- data/lib/geocoder.rb +55 -0
- data/lib/geocoder/cache.rb +85 -0
- data/lib/geocoder/calculations.rb +319 -0
- data/lib/geocoder/cli.rb +114 -0
- data/lib/geocoder/configuration.rb +130 -0
- data/lib/geocoder/configuration_hash.rb +11 -0
- data/lib/geocoder/exceptions.rb +21 -0
- data/lib/geocoder/lookup.rb +82 -0
- data/lib/geocoder/lookups/base.rb +250 -0
- data/lib/geocoder/lookups/bing.rb +47 -0
- data/lib/geocoder/lookups/freegeoip.rb +47 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +54 -0
- data/lib/geocoder/lookups/google.rb +62 -0
- data/lib/geocoder/lookups/google_premier.rb +47 -0
- data/lib/geocoder/lookups/mapquest.rb +43 -0
- data/lib/geocoder/lookups/maxmind.rb +88 -0
- data/lib/geocoder/lookups/nominatim.rb +45 -0
- data/lib/geocoder/lookups/ovi.rb +52 -0
- data/lib/geocoder/lookups/test.rb +38 -0
- data/lib/geocoder/lookups/yahoo.rb +84 -0
- data/lib/geocoder/lookups/yandex.rb +54 -0
- data/lib/geocoder/models/active_record.rb +46 -0
- data/lib/geocoder/models/base.rb +42 -0
- data/lib/geocoder/models/mongo_base.rb +60 -0
- data/lib/geocoder/models/mongo_mapper.rb +26 -0
- data/lib/geocoder/models/mongoid.rb +32 -0
- data/lib/geocoder/query.rb +103 -0
- data/lib/geocoder/railtie.rb +26 -0
- data/lib/geocoder/request.rb +23 -0
- data/lib/geocoder/results/base.rb +67 -0
- data/lib/geocoder/results/bing.rb +48 -0
- data/lib/geocoder/results/freegeoip.rb +45 -0
- data/lib/geocoder/results/geocoder_ca.rb +60 -0
- data/lib/geocoder/results/google.rb +106 -0
- data/lib/geocoder/results/google_premier.rb +6 -0
- data/lib/geocoder/results/mapquest.rb +51 -0
- data/lib/geocoder/results/maxmind.rb +136 -0
- data/lib/geocoder/results/nominatim.rb +94 -0
- data/lib/geocoder/results/ovi.rb +62 -0
- data/lib/geocoder/results/test.rb +16 -0
- data/lib/geocoder/results/yahoo.rb +55 -0
- data/lib/geocoder/results/yandex.rb +80 -0
- data/lib/geocoder/sql.rb +106 -0
- data/lib/geocoder/stores/active_record.rb +259 -0
- data/lib/geocoder/stores/base.rb +120 -0
- data/lib/geocoder/stores/mongo_base.rb +85 -0
- data/lib/geocoder/stores/mongo_mapper.rb +13 -0
- data/lib/geocoder/stores/mongoid.rb +13 -0
- data/lib/geocoder/version.rb +3 -0
- data/lib/hash_recursive_merge.rb +74 -0
- data/lib/oauth_util.rb +112 -0
- data/lib/tasks/geocoder.rake +25 -0
- data/test/active_record_test.rb +15 -0
- data/test/cache_test.rb +19 -0
- data/test/calculations_test.rb +195 -0
- data/test/configuration_test.rb +78 -0
- data/test/custom_block_test.rb +32 -0
- data/test/error_handling_test.rb +43 -0
- data/test/fixtures/bing_invalid_key +1 -0
- data/test/fixtures/bing_madison_square_garden +40 -0
- data/test/fixtures/bing_no_results +16 -0
- data/test/fixtures/bing_reverse +42 -0
- data/test/fixtures/freegeoip_74_200_247_59 +12 -0
- data/test/fixtures/freegeoip_no_results +1 -0
- data/test/fixtures/geocoder_ca_madison_square_garden +1 -0
- data/test/fixtures/geocoder_ca_no_results +1 -0
- data/test/fixtures/geocoder_ca_reverse +34 -0
- data/test/fixtures/google_garbage +456 -0
- data/test/fixtures/google_madison_square_garden +57 -0
- data/test/fixtures/google_no_city_data +44 -0
- data/test/fixtures/google_no_locality +51 -0
- data/test/fixtures/google_no_results +4 -0
- data/test/fixtures/mapquest_madison_square_garden +52 -0
- data/test/fixtures/mapquest_no_results +7 -0
- data/test/fixtures/maxmind_24_24_24_21 +1 -0
- data/test/fixtures/maxmind_24_24_24_22 +1 -0
- data/test/fixtures/maxmind_24_24_24_23 +1 -0
- data/test/fixtures/maxmind_24_24_24_24 +1 -0
- data/test/fixtures/maxmind_74_200_247_59 +1 -0
- data/test/fixtures/maxmind_invalid_key +1 -0
- data/test/fixtures/maxmind_no_results +1 -0
- data/test/fixtures/nominatim_madison_square_garden +150 -0
- data/test/fixtures/nominatim_no_results +1 -0
- data/test/fixtures/ovi_madison_square_garden +72 -0
- data/test/fixtures/ovi_no_results +8 -0
- data/test/fixtures/yahoo_error +1 -0
- data/test/fixtures/yahoo_invalid_key +2 -0
- data/test/fixtures/yahoo_madison_square_garden +52 -0
- data/test/fixtures/yahoo_no_results +10 -0
- data/test/fixtures/yahoo_over_limit +2 -0
- data/test/fixtures/yandex_invalid_key +1 -0
- data/test/fixtures/yandex_kremlin +48 -0
- data/test/fixtures/yandex_no_city_and_town +112 -0
- data/test/fixtures/yandex_no_results +16 -0
- data/test/geocoder_test.rb +59 -0
- data/test/https_test.rb +16 -0
- data/test/integration/smoke_test.rb +26 -0
- data/test/lookup_test.rb +116 -0
- data/test/method_aliases_test.rb +25 -0
- data/test/mongoid_test.rb +39 -0
- data/test/mongoid_test_helper.rb +43 -0
- data/test/near_test.rb +43 -0
- data/test/oauth_util_test.rb +30 -0
- data/test/proxy_test.rb +23 -0
- data/test/query_test.rb +51 -0
- data/test/request_test.rb +29 -0
- data/test/result_test.rb +42 -0
- data/test/services_test.rb +277 -0
- data/test/test_helper.rb +279 -0
- data/test/test_mode_test.rb +50 -0
- metadata +170 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
module Geocoder
|
2
|
+
module Store
|
3
|
+
module Base
|
4
|
+
|
5
|
+
##
|
6
|
+
# Is this object geocoded? (Does it have latitude and longitude?)
|
7
|
+
#
|
8
|
+
def geocoded?
|
9
|
+
to_coordinates.compact.size > 0
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Coordinates [lat,lon] of the object.
|
14
|
+
#
|
15
|
+
def to_coordinates
|
16
|
+
[:latitude, :longitude].map{ |i| send self.class.geocoder_options[i] }
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Calculate the distance from the object to an arbitrary point.
|
21
|
+
# See Geocoder::Calculations.distance_between for ways of specifying
|
22
|
+
# the point. Also takes a symbol specifying the units
|
23
|
+
# (:mi or :km; can be specified in Geocoder configuration).
|
24
|
+
#
|
25
|
+
def distance_to(point, units = nil)
|
26
|
+
units ||= self.class.geocoder_options[:units]
|
27
|
+
return nil unless geocoded?
|
28
|
+
Geocoder::Calculations.distance_between(
|
29
|
+
to_coordinates, point, :units => units)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :distance_from, :distance_to
|
33
|
+
|
34
|
+
##
|
35
|
+
# Calculate the bearing from the object to another point.
|
36
|
+
# See Geocoder::Calculations.distance_between for
|
37
|
+
# ways of specifying the point.
|
38
|
+
#
|
39
|
+
def bearing_to(point, options = {})
|
40
|
+
options[:method] ||= self.class.geocoder_options[:method]
|
41
|
+
return nil unless geocoded?
|
42
|
+
Geocoder::Calculations.bearing_between(
|
43
|
+
to_coordinates, point, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Calculate the bearing from another point to the object.
|
48
|
+
# See Geocoder::Calculations.distance_between for
|
49
|
+
# ways of specifying the point.
|
50
|
+
#
|
51
|
+
def bearing_from(point, options = {})
|
52
|
+
options[:method] ||= self.class.geocoder_options[:method]
|
53
|
+
return nil unless geocoded?
|
54
|
+
Geocoder::Calculations.bearing_between(
|
55
|
+
point, to_coordinates, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Get nearby geocoded objects.
|
60
|
+
# Takes the same options hash as the near class method (scope).
|
61
|
+
# Returns nil if the object is not geocoded.
|
62
|
+
#
|
63
|
+
def nearbys(radius = 20, options = {})
|
64
|
+
return nil unless geocoded?
|
65
|
+
options.merge!(:exclude => self) unless send(self.class.primary_key).nil?
|
66
|
+
self.class.near(self, radius, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
|
71
|
+
# (or other as specified in +geocoded_by+). Returns coordinates (array).
|
72
|
+
#
|
73
|
+
def geocode
|
74
|
+
fail
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Look up address and assign to +address+ attribute (or other as specified
|
79
|
+
# in +reverse_geocoded_by+). Returns address (string).
|
80
|
+
#
|
81
|
+
def reverse_geocode
|
82
|
+
fail
|
83
|
+
end
|
84
|
+
|
85
|
+
private # --------------------------------------------------------------
|
86
|
+
|
87
|
+
##
|
88
|
+
# Look up geographic data based on object attributes (configured in
|
89
|
+
# geocoded_by or reverse_geocoded_by) and handle the results with the
|
90
|
+
# block (given to geocoded_by or reverse_geocoded_by). The block is
|
91
|
+
# given two-arguments: the object being geocoded and an array of
|
92
|
+
# Geocoder::Result objects).
|
93
|
+
#
|
94
|
+
def do_lookup(reverse = false)
|
95
|
+
options = self.class.geocoder_options
|
96
|
+
if reverse and options[:reverse_geocode]
|
97
|
+
query = to_coordinates
|
98
|
+
elsif !reverse and options[:geocode]
|
99
|
+
query = send(options[:user_address])
|
100
|
+
else
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
results = Geocoder.search(query)
|
105
|
+
|
106
|
+
# execute custom block, if specified in configuration
|
107
|
+
block_key = reverse ? :reverse_block : :geocode_block
|
108
|
+
if custom_block = options[block_key]
|
109
|
+
custom_block.call(self, results)
|
110
|
+
|
111
|
+
# else execute block passed directly to this method,
|
112
|
+
# which generally performs the "auto-assigns"
|
113
|
+
elsif block_given?
|
114
|
+
yield(self, results)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Geocoder::Store
|
2
|
+
module MongoBase
|
3
|
+
|
4
|
+
def self.included_by_model(base)
|
5
|
+
base.class_eval do
|
6
|
+
|
7
|
+
scope :geocoded, lambda {
|
8
|
+
where(geocoder_options[:coordinates].ne => nil)
|
9
|
+
}
|
10
|
+
|
11
|
+
scope :not_geocoded, lambda {
|
12
|
+
where(geocoder_options[:coordinates] => nil)
|
13
|
+
}
|
14
|
+
|
15
|
+
scope :near, lambda{ |location, *args|
|
16
|
+
coords = Geocoder::Calculations.extract_coordinates(location)
|
17
|
+
|
18
|
+
# no results if no lat/lon given
|
19
|
+
return where(:id => false) unless coords.is_a?(Array)
|
20
|
+
|
21
|
+
radius = args.size > 0 ? args.shift : 20
|
22
|
+
options = args.size > 0 ? args.shift : {}
|
23
|
+
options[:units] ||= geocoder_options[:units]
|
24
|
+
|
25
|
+
# Use BSON::OrderedHash if Ruby's hashes are unordered.
|
26
|
+
# Conditions must be in order required by indexes (see mongo gem).
|
27
|
+
empty = RUBY_VERSION.split('.')[1].to_i < 9 ? BSON::OrderedHash.new : {}
|
28
|
+
|
29
|
+
conds = empty.clone
|
30
|
+
field = geocoder_options[:coordinates]
|
31
|
+
conds[field] = empty.clone
|
32
|
+
conds[field]["$nearSphere"] = coords.reverse
|
33
|
+
conds[field]["$maxDistance"] = \
|
34
|
+
Geocoder::Calculations.distance_to_radians(radius, options[:units])
|
35
|
+
|
36
|
+
if obj = options[:exclude]
|
37
|
+
conds[:_id.ne] = obj.id
|
38
|
+
end
|
39
|
+
where(conds)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Coordinates [lat,lon] of the object.
|
46
|
+
# This method always returns coordinates in lat,lon order,
|
47
|
+
# even though internally they are stored in the opposite order.
|
48
|
+
#
|
49
|
+
def to_coordinates
|
50
|
+
coords = send(self.class.geocoder_options[:coordinates])
|
51
|
+
coords.is_a?(Array) ? coords.reverse : []
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Look up coordinates and assign to +latitude+ and +longitude+ attributes
|
56
|
+
# (or other as specified in +geocoded_by+). Returns coordinates (array).
|
57
|
+
#
|
58
|
+
def geocode
|
59
|
+
do_lookup(false) do |o,rs|
|
60
|
+
if r = rs.first
|
61
|
+
unless r.coordinates.nil?
|
62
|
+
o.__send__ "#{self.class.geocoder_options[:coordinates]}=", r.coordinates.reverse
|
63
|
+
end
|
64
|
+
r.coordinates
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Look up address and assign to +address+ attribute (or other as specified
|
71
|
+
# in +reverse_geocoded_by+). Returns address (string).
|
72
|
+
#
|
73
|
+
def reverse_geocode
|
74
|
+
do_lookup(true) do |o,rs|
|
75
|
+
if r = rs.first
|
76
|
+
unless r.address.nil?
|
77
|
+
o.__send__ "#{self.class.geocoder_options[:fetched_address]}=", r.address
|
78
|
+
end
|
79
|
+
r.address
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# = Hash Recursive Merge
|
3
|
+
#
|
4
|
+
# Merges a Ruby Hash recursively, Also known as deep merge.
|
5
|
+
# Recursive version of Hash#merge and Hash#merge!.
|
6
|
+
#
|
7
|
+
# Category:: Ruby
|
8
|
+
# Package:: Hash
|
9
|
+
# Author:: Simone Carletti <weppos@weppos.net>
|
10
|
+
# Copyright:: 2007-2008 The Authors
|
11
|
+
# License:: MIT License
|
12
|
+
# Link:: http://www.simonecarletti.com/
|
13
|
+
# Source:: http://gist.github.com/gists/6391/
|
14
|
+
#
|
15
|
+
module HashRecursiveMerge
|
16
|
+
|
17
|
+
#
|
18
|
+
# Recursive version of Hash#merge!
|
19
|
+
#
|
20
|
+
# Adds the contents of +other_hash+ to +hsh+,
|
21
|
+
# merging entries in +hsh+ with duplicate keys with those from +other_hash+.
|
22
|
+
#
|
23
|
+
# Compared with Hash#merge!, this method supports nested hashes.
|
24
|
+
# When both +hsh+ and +other_hash+ contains an entry with the same key,
|
25
|
+
# it merges and returns the values from both arrays.
|
26
|
+
#
|
27
|
+
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
|
28
|
+
# h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
|
29
|
+
# h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
|
30
|
+
#
|
31
|
+
# Simply using Hash#merge! would return
|
32
|
+
#
|
33
|
+
# h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
|
34
|
+
#
|
35
|
+
def rmerge!(other_hash)
|
36
|
+
merge!(other_hash) do |key, oldval, newval|
|
37
|
+
oldval.class == self.class ? oldval.rmerge!(newval) : newval
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Recursive version of Hash#merge
|
43
|
+
#
|
44
|
+
# Compared with Hash#merge!, this method supports nested hashes.
|
45
|
+
# When both +hsh+ and +other_hash+ contains an entry with the same key,
|
46
|
+
# it merges and returns the values from both arrays.
|
47
|
+
#
|
48
|
+
# Compared with Hash#merge, this method provides a different approch
|
49
|
+
# for merging nasted hashes.
|
50
|
+
# If the value of a given key is an Hash and both +other_hash+ abd +hsh
|
51
|
+
# includes the same key, the value is merged instead replaced with
|
52
|
+
# +other_hash+ value.
|
53
|
+
#
|
54
|
+
# h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
|
55
|
+
# h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
|
56
|
+
# h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
|
57
|
+
#
|
58
|
+
# Simply using Hash#merge would return
|
59
|
+
#
|
60
|
+
# h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
|
61
|
+
#
|
62
|
+
def rmerge(other_hash)
|
63
|
+
r = {}
|
64
|
+
merge(other_hash) do |key, oldval, newval|
|
65
|
+
r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
class Hash
|
73
|
+
include HashRecursiveMerge
|
74
|
+
end
|
data/lib/oauth_util.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# A utility for signing an url using OAuth in a way that's convenient for debugging
|
2
|
+
# Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth
|
3
|
+
# Source: http://gist.github.com/383159
|
4
|
+
# License: http://gist.github.com/375593
|
5
|
+
# Usage: see example.rb below
|
6
|
+
#
|
7
|
+
# NOTE: This file has been modified from the original Gist:
|
8
|
+
#
|
9
|
+
# 1. Fix to prevent param-array conversion, as mentioned in Gist comment.
|
10
|
+
# 2. Query string escaping has been changed. See:
|
11
|
+
# https://github.com/alexreisner/geocoder/pull/360
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'uri'
|
15
|
+
require 'cgi'
|
16
|
+
require 'openssl'
|
17
|
+
require 'base64'
|
18
|
+
|
19
|
+
class OauthUtil
|
20
|
+
|
21
|
+
attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
|
22
|
+
:sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@consumer_key = ''
|
26
|
+
@consumer_secret = ''
|
27
|
+
@token = ''
|
28
|
+
@token_secret = ''
|
29
|
+
@req_method = 'GET'
|
30
|
+
@sig_method = 'HMAC-SHA1'
|
31
|
+
@oauth_version = '1.0'
|
32
|
+
@callback_url = ''
|
33
|
+
end
|
34
|
+
|
35
|
+
# openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length
|
36
|
+
# ref http://snippets.dzone.com/posts/show/491
|
37
|
+
def nonce
|
38
|
+
Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
|
39
|
+
end
|
40
|
+
|
41
|
+
def percent_encode( string )
|
42
|
+
|
43
|
+
# ref http://snippets.dzone.com/posts/show/1260
|
44
|
+
return URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A')
|
45
|
+
end
|
46
|
+
|
47
|
+
# @ref http://oauth.net/core/1.0/#rfc.section.9.2
|
48
|
+
def signature
|
49
|
+
key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )
|
50
|
+
|
51
|
+
# ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
|
52
|
+
digest = OpenSSL::Digest::Digest.new( 'sha1' )
|
53
|
+
hmac = OpenSSL::HMAC.digest( digest, key, @base_str )
|
54
|
+
|
55
|
+
# ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
|
56
|
+
Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
|
57
|
+
end
|
58
|
+
|
59
|
+
# sort (very important as it affects the signature), concat, and percent encode
|
60
|
+
# @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
|
61
|
+
# @ref http://oauth.net/core/1.0/#9.2.1
|
62
|
+
# @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
|
63
|
+
def query_string
|
64
|
+
pairs = []
|
65
|
+
@params.sort.each { | key, val |
|
66
|
+
pairs.push( "#{ CGI.escape(key.to_s).gsub(/%(5B|5D)/n) { [$1].pack('H*') } }=#{ CGI.escape(val.to_s) }" )
|
67
|
+
}
|
68
|
+
pairs.join '&'
|
69
|
+
end
|
70
|
+
|
71
|
+
# organize params & create signature
|
72
|
+
def sign( parsed_url )
|
73
|
+
|
74
|
+
@params = {
|
75
|
+
'oauth_consumer_key' => @consumer_key,
|
76
|
+
'oauth_nonce' => nonce,
|
77
|
+
'oauth_signature_method' => @sig_method,
|
78
|
+
'oauth_timestamp' => Time.now.to_i.to_s,
|
79
|
+
'oauth_version' => @oauth_version
|
80
|
+
}
|
81
|
+
|
82
|
+
# if url has query, merge key/values into params obj overwriting defaults
|
83
|
+
if parsed_url.query
|
84
|
+
CGI.parse( parsed_url.query ).each do |k,v|
|
85
|
+
if v.is_a?(Array) && v.count == 1
|
86
|
+
@params[k] = v.first
|
87
|
+
else
|
88
|
+
@params[k] = v
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
|
94
|
+
@req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
|
95
|
+
|
96
|
+
# create base str. make it an object attr for ez debugging
|
97
|
+
# ref http://oauth.net/core/1.0/#anchor14
|
98
|
+
@base_str = [
|
99
|
+
@req_method,
|
100
|
+
percent_encode( req_url ),
|
101
|
+
|
102
|
+
# normalization is just x-www-form-urlencoded
|
103
|
+
percent_encode( query_string )
|
104
|
+
|
105
|
+
].join( '&' )
|
106
|
+
|
107
|
+
# add signature
|
108
|
+
@params[ 'oauth_signature' ] = signature
|
109
|
+
|
110
|
+
return self
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
namespace :geocode do
|
2
|
+
desc "Geocode all objects without coordinates."
|
3
|
+
task :all => :environment do
|
4
|
+
class_name = ENV['CLASS'] || ENV['class']
|
5
|
+
raise "Please specify a CLASS (model)" unless class_name
|
6
|
+
klass = class_from_string(class_name)
|
7
|
+
|
8
|
+
klass.not_geocoded.each do |obj|
|
9
|
+
obj.geocode; obj.save
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Get a class object from the string given in the shell environment.
|
16
|
+
# Similar to ActiveSupport's +constantize+ method.
|
17
|
+
#
|
18
|
+
def class_from_string(class_name)
|
19
|
+
parts = class_name.split("::")
|
20
|
+
constant = Object
|
21
|
+
parts.each do |part|
|
22
|
+
constant = constant.const_get(part)
|
23
|
+
end
|
24
|
+
constant
|
25
|
+
end
|