graticule 2.2.0 → 2.3.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.
@@ -1,3 +1,12 @@
1
+ 2.3.0 (2013-04-01)
2
+ * Google v3 API [Adamlb]
3
+ * Escape XML entities in GeoCoder::MapQuest queries [Simon Coffey]
4
+
5
+ 2.2.0 (2011-09-14)
6
+ * Added yandex geocoder
7
+ * Lots of other changes since September 2009.
8
+ Check https://github.com/collectiveidea/graticule/compare/v0.2.12...master for more info
9
+
1
10
  * Added freethepostcode.org geocoder [Chris Lowis]
2
11
 
3
12
  0.2.12 (2009-09-06)
@@ -38,16 +38,15 @@ module Graticule
38
38
  :latitude_column => 'latitude',
39
39
  :longitude_column => 'longitude'
40
40
  }.merge(options)
41
- %{(ACOS(
41
+ %{(ACOS(LEAST(1,
42
42
  SIN(RADIANS(#{options[:latitude]})) *
43
43
  SIN(RADIANS(#{options[:latitude_column]})) +
44
44
  COS(RADIANS(#{options[:latitude]})) *
45
45
  COS(RADIANS(#{options[:latitude_column]})) *
46
46
  COS(RADIANS(#{options[:longitude_column]}) - RADIANS(#{options[:longitude]}))
47
- ) * #{Graticule::Distance::EARTH_RADIUS[options[:units].to_sym]})
47
+ )) * #{Graticule::Distance::EARTH_RADIUS[options[:units].to_sym]})
48
48
  }.gsub("\n", '').squeeze(" ")
49
49
  end
50
-
51
50
  end
52
51
  end
53
52
  end
@@ -81,6 +81,7 @@ module Graticule #:nodoc:
81
81
  check_error(response)
82
82
  return parse_response(response)
83
83
  rescue OpenURI::HTTPError => e
84
+ raise e.inspect
84
85
  check_error(prepare_response(e.io.read))
85
86
  raise
86
87
  end
@@ -91,7 +92,6 @@ module Graticule #:nodoc:
91
92
  escaped_params = params.sort_by { |k,v| k.to_s }.map do |k,v|
92
93
  "#{escape k.to_s}=#{escape v.to_s}"
93
94
  end
94
-
95
95
  url = @url.dup
96
96
  url.query = escaped_params.join '&'
97
97
  return url
@@ -1,93 +1,102 @@
1
1
  # encoding: UTF-8
2
+ require 'json'
2
3
  module Graticule #:nodoc:
3
4
  module Geocoder #:nodoc:
4
-
5
- # First you need a Google Maps API key. You can register for one here:
6
- # http://www.google.com/apis/maps/signup.html
7
- #
8
- # gg = Graticule.service(:google).new(MAPS_API_KEY)
5
+ # gg = Graticule.service(:google).new(MAPS_API_KEY) API Key is not required
9
6
  # location = gg.locate '1600 Amphitheater Pkwy, Mountain View, CA'
10
7
  # p location.coordinates
11
8
  # #=> [37.423111, -122.081783
12
9
  #
13
10
  class Google < Base
14
- # http://www.google.com/apis/maps/documentation/#Geocoding_HTTP_Request
15
-
16
- # http://www.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
17
- PRECISION = {
18
- 0 => Precision::Unknown, # Unknown location.
19
- 1 => Precision::Country, # Country level accuracy.
20
- 2 => Precision::Region, # Region (state, province, prefecture, etc.) level accuracy.
21
- 3 => Precision::Region, # Sub-region (county, municipality, etc.) level accuracy.
22
- 4 => Precision::Locality, # Town (city, village) level accuracy.
23
- 5 => Precision::PostalCode, # Post code (zip code) level accuracy.
24
- 6 => Precision::Street, # Street level accuracy.
25
- 7 => Precision::Street, # Intersection level accuracy.
26
- 8 => Precision::Address, # Address level accuracy.
27
- 9 => Precision::Premise # Premise (building name, property name, shopping center, etc.) level accuracy.
28
- }
11
+ # https://developers.google.com/maps/documentation/geocoding/
29
12
 
30
13
  def initialize(key)
31
14
  @key = key
32
- @url = URI.parse 'http://maps.google.com/maps/geo'
15
+ @url = URI.parse 'http://maps.googleapis.com/maps/api/geocode/json'
33
16
  end
34
17
 
35
18
  # Locates +address+ returning a Location
36
19
  def locate(address)
37
- get :q => address.is_a?(String) ? address : location_from_params(address).to_s
20
+ get :address => address.is_a?(String) ? address : location_from_params(address).to_s
38
21
  end
39
22
 
40
23
  private
41
- class Address
42
- include HappyMapper
43
- tag 'AddressDetails'
44
- namespace 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'
45
-
46
- attribute :accuracy, Integer, :tag => 'Accuracy'
47
- end
48
-
49
- class Placemark
50
- include HappyMapper
51
- tag 'Placemark'
52
- element :coordinates, String, :deep => true
53
- has_one :address, Address
54
-
55
- attr_reader :longitude, :latitude
56
-
57
- with_options :deep => true, :namespace => 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0' do |map|
58
- map.element :street, String, :tag => 'ThoroughfareName'
59
- map.element :locality, String, :tag => 'LocalityName'
60
- map.element :region, String, :tag => 'AdministrativeAreaName'
61
- map.element :postal_code, String, :tag => 'PostalCodeNumber'
62
- map.element :country, String, :tag => 'CountryNameCode'
24
+ class Result
25
+ attr_accessor :latitude, :longitude, :street_number, :route, :locality, :region, :postal_code, :country, :precision, :formatted_address
26
+ def initialize(attribs)
27
+ @latitude = attribs["geometry"]["location"]["lat"]
28
+ @longitude = attribs["geometry"]["location"]["lng"]
29
+ @formatted_address = attribs["formatted_address"]
30
+ @precision = determine_precision(attribs["types"])
31
+ parse_address_components(attribs["address_components"])
63
32
  end
64
33
 
65
- def coordinates=(coordinates)
66
- @longitude, @latitude, _ = coordinates.split(',').map { |v| v.to_f }
34
+ def parse_address_components(components)
35
+ components.each do |component|
36
+ component["types"].each do |type|
37
+ case type
38
+ when "street_number"
39
+ @street_number = component["short_name"]
40
+ when "route"
41
+ @route = component["short_name"]
42
+ when "locality"
43
+ @locality = component["long_name"]
44
+ when "administrative_area_level_1"
45
+ @region = component["short_name"]
46
+ when "country"
47
+ @country = component["short_name"]
48
+ when "postal_code"
49
+ @postal_code = component["long_name"]
50
+ end
51
+ end
52
+ end
67
53
  end
68
54
 
69
- def accuracy
70
- address.accuracy if address
55
+ def street
56
+ "#{@street_number.to_s}#{" " unless @street_number.blank? || @route.blank?}#{@route.to_s}"
71
57
  end
72
58
 
73
- def precision
74
- PRECISION[accuracy] || :unknown
59
+ def determine_precision(types)
60
+ precision = Precision::Unknown
61
+ types.each do |type|
62
+ precision = case type
63
+ when "premise", "subpremise"
64
+ Precision::Premise
65
+ when "street_address"
66
+ Precision::Address
67
+ when "route", "intersection"
68
+ Precision::Street
69
+ when "postal_code"
70
+ Precision::PostalCode
71
+ when "locality","sublocality","neighborhood"
72
+ Precision::Locality
73
+ when "administrative_area_level_1", "administrative_area_level_2","administrative_area_level_3"
74
+ Precision::Region
75
+ when "country"
76
+ Precision::Country
77
+ else
78
+ precision
79
+ end
80
+ end
81
+ return precision
75
82
  end
76
83
  end
77
84
 
78
85
  class Response
79
- include HappyMapper
80
- tag 'Response'
81
- element :code, Integer, :tag => 'code', :deep => true
82
- has_many :placemarks, Placemark
86
+ attr_reader :results, :status
87
+ def initialize(json)
88
+ result = JSON.parse(json)
89
+ @results = result["results"].collect{|attribs| Result.new(attribs)}
90
+ @status = result["status"]
91
+ end
83
92
  end
84
93
 
85
- def prepare_response(xml)
86
- Response.parse(xml, :single => true)
94
+ def prepare_response(json)
95
+ Response.new(json)
87
96
  end
88
97
 
89
98
  def parse_response(response) #:nodoc:
90
- result = response.placemarks.first
99
+ result = response.results.first
91
100
  Location.new(
92
101
  :latitude => result.latitude,
93
102
  :longitude => result.longitude,
@@ -100,31 +109,28 @@ module Graticule #:nodoc:
100
109
  )
101
110
  end
102
111
 
103
- # Extracts and raises an error from +xml+, if any.
112
+ # Extracts and raises an error from +json+, if any.
104
113
  def check_error(response) #:nodoc:
105
- case response.code
106
- when 200 then # ignore, ok
107
- when 500 then
108
- raise Error, 'server error'
109
- when 601 then
110
- raise AddressError, 'missing address'
111
- when 602 then
114
+ case response.status
115
+ when "OK" then # ignore, ok
116
+ when "ZERO_RESULTS" then
112
117
  raise AddressError, 'unknown address'
113
- when 603 then
114
- raise AddressError, 'unavailable address'
115
- when 610 then
116
- raise CredentialsError, 'invalid key'
117
- when 620 then
118
- raise CredentialsError, 'too many queries'
118
+ when "OVER_QUERY_LIMIT"
119
+ raise CredentialsError, 'over query limit'
120
+ when "REQUEST_DENIED"
121
+ raise CredentialsError, 'request denied'
122
+ when "INVALID_REQUEST"
123
+ raise AddressError, 'missing address'
124
+ when "UNKNOWN_ERROR"
125
+ raise Error, "unknown server error. Try again."
119
126
  else
120
- raise Error, "unknown error #{response.code}"
127
+ raise Error, "unkown error #{response.status}"
121
128
  end
122
129
  end
123
130
 
124
- # Creates a URL from the Hash +params+.
125
- # sets the output type to 'xml'.
131
+ # Creates a URL from the Hash +params+..
126
132
  def make_url(params) #:nodoc:
127
- super params.merge(:key => @key, :oe => 'utf8', :output => 'xml', :sensor => false)
133
+ super params.merge(:key => @key, :sensor => false)
128
134
  end
129
135
  end
130
136
  end
@@ -1,3 +1,5 @@
1
+ require 'htmlentities'
2
+
1
3
  # encoding: UTF-8
2
4
  module Graticule #:nodoc:
3
5
  module Geocoder #:nodoc:
@@ -43,13 +45,36 @@ module Graticule #:nodoc:
43
45
  protected
44
46
 
45
47
  def make_url(params) #:nodoc
46
- query = "e=5&<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><Geocode Version=\"1\"> \
47
- #{address_string(params[:q])}#{authentication_string}</Geocode>"
48
+ request = Mapquest::Request.new(params[:q], @client_id, @password)
48
49
  url = @url.dup
49
- url.query = escape(query)
50
+ url.query = escape(request.query)
50
51
  url
51
52
  end
52
53
 
54
+ class Request
55
+ def initialize(address, client_id, password)
56
+ @address = address
57
+ @client_id = client_id
58
+ @password = password
59
+ end
60
+
61
+ def query
62
+ "e=5&<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><Geocode Version=\"1\">#{address_string}#{authentication_string}</Geocode>"
63
+ end
64
+
65
+ def address_string
66
+ "<Address><Street>#{escaped_address}</Street></Address><GeocodeOptionsCollection Count=\"0\"/>"
67
+ end
68
+
69
+ def authentication_string
70
+ "<Authentication Version=\"2\"><Password>#{@password}</Password><ClientId>#{@client_id}</ClientId></Authentication>"
71
+ end
72
+
73
+ def escaped_address
74
+ HTMLEntities.new.encode(@address, :basic)
75
+ end
76
+ end
77
+
53
78
  class Address
54
79
  include HappyMapper
55
80
  tag 'GeoAddress'
@@ -96,13 +121,6 @@ module Graticule #:nodoc:
96
121
  def check_error(xml) #:nodoc
97
122
  end
98
123
 
99
- def authentication_string
100
- "<Authentication Version=\"2\"><Password>#{@password}</Password><ClientId>#{@client_id}</ClientId></Authentication>"
101
- end
102
-
103
- def address_string(query)
104
- "<Address><Street>#{query}</Street></Address><GeocodeOptionsCollection Count=\"0\"/>"
105
- end
106
124
  end
107
125
  end
108
126
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module Graticule
3
- VERSION = '2.2.0' unless defined?(::Graticule::VERSION)
3
+ VERSION = '2.3.0' unless defined?(::Graticule::VERSION)
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graticule
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-09-14 00:00:00.000000000Z
13
+ date: 2013-04-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
17
- requirement: &70276838707980 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70276838707980
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: i18n
28
- requirement: &70276838705640 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ! '>='
@@ -33,10 +38,31 @@ dependencies:
33
38
  version: '0'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *70276838705640
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: htmlentities
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
37
63
  - !ruby/object:Gem::Dependency
38
64
  name: happymapper
39
- requirement: &70276838703420 !ruby/object:Gem::Requirement
65
+ requirement: !ruby/object:Gem::Requirement
40
66
  none: false
41
67
  requirements:
42
68
  - - ! '>='
@@ -44,10 +70,15 @@ dependencies:
44
70
  version: 0.3.0
45
71
  type: :runtime
46
72
  prerelease: false
47
- version_requirements: *70276838703420
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: 0.3.0
48
79
  - !ruby/object:Gem::Dependency
49
80
  name: json
50
- requirement: &70276838701800 !ruby/object:Gem::Requirement
81
+ requirement: !ruby/object:Gem::Requirement
51
82
  none: false
52
83
  requirements:
53
84
  - - ! '>='
@@ -55,10 +86,15 @@ dependencies:
55
86
  version: '0'
56
87
  type: :runtime
57
88
  prerelease: false
58
- version_requirements: *70276838701800
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
59
95
  - !ruby/object:Gem::Dependency
60
96
  name: mocha
61
- requirement: &70276838699580 !ruby/object:Gem::Requirement
97
+ requirement: !ruby/object:Gem::Requirement
62
98
  none: false
63
99
  requirements:
64
100
  - - ! '>='
@@ -66,10 +102,15 @@ dependencies:
66
102
  version: '0'
67
103
  type: :development
68
104
  prerelease: false
69
- version_requirements: *70276838699580
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
70
111
  - !ruby/object:Gem::Dependency
71
112
  name: rcov
72
- requirement: &70276838697520 !ruby/object:Gem::Requirement
113
+ requirement: !ruby/object:Gem::Requirement
73
114
  none: false
74
115
  requirements:
75
116
  - - ! '>='
@@ -77,7 +118,12 @@ dependencies:
77
118
  version: '0'
78
119
  type: :development
79
120
  prerelease: false
80
- version_requirements: *70276838697520
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
81
127
  description: Graticule is a geocoding API that provides a common interface to all
82
128
  the popular services, including Google, Yahoo, Geocoder.us, and MetaCarta.
83
129
  email: brandon@opensoul.org
@@ -135,7 +181,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
181
  version: '0'
136
182
  segments:
137
183
  - 0
138
- hash: 473484385783211524
184
+ hash: 3804880588215325222
139
185
  required_rubygems_version: !ruby/object:Gem::Requirement
140
186
  none: false
141
187
  requirements:
@@ -144,10 +190,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
190
  version: '0'
145
191
  segments:
146
192
  - 0
147
- hash: 473484385783211524
193
+ hash: 3804880588215325222
148
194
  requirements: []
149
195
  rubyforge_project: graticule
150
- rubygems_version: 1.8.6
196
+ rubygems_version: 1.8.25
151
197
  signing_key:
152
198
  specification_version: 3
153
199
  summary: API for using all the popular geocoding services.