graticule 2.0.1 → 2.1.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.
data/lib/graticule.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  $:.unshift(File.dirname(__FILE__))
2
3
 
3
4
  require 'active_support'
data/lib/graticule/cli.rb CHANGED
@@ -1,11 +1,12 @@
1
+ # encoding: UTF-8
1
2
  require 'graticule'
2
3
  require 'optparse'
3
4
 
4
5
  module Graticule
5
-
6
+
6
7
  # A command line interface for geocoding. From the command line, run:
7
8
  #
8
- # geocode 49423
9
+ # geocode 49423
9
10
  #
10
11
  # Outputs:
11
12
  #
@@ -13,16 +14,16 @@ module Graticule
13
14
  # # latitude: 42.7654, longitude: -86.1085
14
15
  #
15
16
  # == Usage: geocode [options] location
16
- #
17
- # Options:
17
+ #
18
+ # Options:
18
19
  # -s, --service service Geocoding service
19
20
  # -a, --apikey apikey API key for the selected service
20
21
  # -h, --help Help
21
22
  class Cli
22
-
23
+
23
24
  def self.start(args, out = STDOUT)
24
25
  options = { :service => :yahoo, :api_key => 'YahooDemo' }
25
-
26
+
26
27
  OptionParser.new do |opts|
27
28
  opts.banner = "Usage: geocode [options] location"
28
29
  opts.separator ""
@@ -31,9 +32,9 @@ module Graticule
31
32
  opts.on("-s service", %w(yahoo google geocoder_us metacarta), "--service service", "Geocoding service") do |service|
32
33
  options[:service] = service
33
34
  end
34
-
35
+
35
36
  opts.on("-a apikey", "--apikey apikey", "API key for the selected service")
36
-
37
+
37
38
  opts.on_tail("-h", "--help", "Help") do
38
39
  puts opts
39
40
  exit
@@ -41,7 +42,7 @@ module Graticule
41
42
  end.parse! args
42
43
 
43
44
  options[:location] = args.join(" ")
44
-
45
+
45
46
  result = Graticule.service(options[:service]).new(*options[:api_key].split(',')).locate(options[:location])
46
47
  location = (result.is_a?(Array) ? result.first : result)
47
48
  if location
@@ -57,8 +58,8 @@ module Graticule
57
58
  Graticule::Error => error
58
59
  $stderr.puts error.message
59
60
  end
60
-
61
-
61
+
62
+
62
63
  end
63
64
  end
64
65
 
@@ -1,10 +1,11 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
  module RadiansAndDegrees
3
4
  # Convert from degrees to radians
4
5
  def to_radians
5
6
  ( self / 360.0 ) * Math::PI * 2
6
7
  end
7
-
8
+
8
9
  # Convert from radians to degrees
9
10
  def to_degrees
10
11
  ( self * 360.0 ) / Math::PI / 2
@@ -12,4 +13,4 @@ module Graticule
12
13
  end
13
14
  end
14
15
 
15
- Numeric.send :include, Graticule::RadiansAndDegrees
16
+ Numeric.send :include, Graticule::RadiansAndDegrees
@@ -1,6 +1,7 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
  module Distance
3
-
4
+
4
5
  EARTH_RADIUS = { :kilometers => 6378.135, :miles => 3963.1676 }
5
6
  # WGS-84 numbers
6
7
  EARTH_MAJOR_AXIS_RADIUS = { :kilometers => 6378.137, :miles => 3963.19059 }
@@ -9,7 +10,7 @@ module Graticule
9
10
  class DistanceFormula
10
11
  include Math
11
12
  extend Math
12
-
13
+
13
14
  def initialize
14
15
  raise NotImplementedError
15
16
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
  module Distance
3
4
  #
@@ -7,7 +8,7 @@ module Graticule
7
8
  # for distance formulas.
8
9
  #
9
10
  class Haversine < DistanceFormula
10
-
11
+
11
12
  # Calculate the distance between two Locations using the Haversine formula
12
13
  #
13
14
  # Graticule::Distance::Haversine.distance(
@@ -25,9 +26,9 @@ module Graticule
25
26
  latitude_delta = to_latitude - from_latitude
26
27
  longitude_delta = to_longitude - from_longitude
27
28
 
28
- a = sin(latitude_delta/2)**2 +
29
- cos(from_latitude) *
30
- cos(to_latitude) *
29
+ a = sin(latitude_delta/2)**2 +
30
+ cos(from_latitude) *
31
+ cos(to_latitude) *
31
32
  sin(longitude_delta/2)**2
32
33
 
33
34
  c = 2 * atan2(sqrt(a), sqrt(1-a))
@@ -37,4 +38,4 @@ module Graticule
37
38
 
38
39
  end
39
40
  end
40
- end
41
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
  module Distance
3
4
 
@@ -25,7 +26,7 @@ module Graticule
25
26
  Math.sin(from_latitude) *
26
27
  Math.sin(to_latitude) +
27
28
 
28
- Math.cos(from_latitude) *
29
+ Math.cos(from_latitude) *
29
30
  Math.cos(to_latitude) *
30
31
  Math.cos(to_longitude - from_longitude)
31
32
  ) * EARTH_RADIUS[units.to_sym]
@@ -46,7 +47,7 @@ module Graticule
46
47
  ) * #{Graticule::Distance::EARTH_RADIUS[options[:units].to_sym]})
47
48
  }.gsub("\n", '').squeeze(" ")
48
49
  end
49
-
50
+
50
51
  end
51
52
  end
52
- end
53
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
  module Distance
3
4
 
@@ -73,4 +74,4 @@ module Graticule
73
74
 
74
75
  end
75
76
  end
76
- end
77
+ end
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  require 'happymapper'
2
3
 
3
4
  module Graticule
4
-
5
+
5
6
  # Get a geocoder for the given service
6
7
  #
7
8
  # geocoder = Graticule.service(:google).new "api_key"
@@ -11,7 +12,7 @@ module Graticule
11
12
  def self.service(name)
12
13
  Geocoder.const_get name.to_s.camelize
13
14
  end
14
-
15
+
15
16
  # Base error class
16
17
  class Error < RuntimeError; end
17
18
  class CredentialsError < Error; end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'open-uri'
2
3
 
3
4
  module Graticule #:nodoc:
@@ -22,7 +23,7 @@ module Graticule #:nodoc:
22
23
  # perform URL customization, override +make_url+.
23
24
  #
24
25
  # class FakeGeocoder < Base
25
- #
26
+ #
26
27
  # def initialize(appid)
27
28
  # @appid = appid
28
29
  # @url = URI.parse 'http://example.com/test'
@@ -31,22 +32,22 @@ module Graticule #:nodoc:
31
32
  # def locate(query)
32
33
  # get :q => query
33
34
  # end
34
- #
35
+ #
35
36
  # private
36
- #
37
+ #
37
38
  # def check_error(xml)
38
39
  # raise Error, xml.elements['error'].text if xml.elements['error']
39
40
  # end
40
- #
41
+ #
41
42
  # def make_url(params)
42
43
  # params[:appid] = @appid
43
44
  # super params
44
45
  # end
45
- #
46
+ #
46
47
  # def parse_response(response)
47
48
  # # return Location
48
49
  # end
49
- #
50
+ #
50
51
  # end
51
52
  #
52
53
  class Base
@@ -55,9 +56,9 @@ module Graticule #:nodoc:
55
56
  def initialize
56
57
  raise NotImplementedError
57
58
  end
58
-
59
+
59
60
  private
60
-
61
+
61
62
  def location_from_params(params)
62
63
  case params
63
64
  when Location then params
@@ -95,7 +96,7 @@ module Graticule #:nodoc:
95
96
  url.query = escaped_params.join '&'
96
97
  return url
97
98
  end
98
-
99
+
99
100
  # Override to convert the response to something besides a String, which
100
101
  # will get passed to +check_error+ and +parse_response+.
101
102
  def prepare_response(response)
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
  # Bogus geocoder that can be used for test purposes
@@ -5,10 +6,10 @@ module Graticule #:nodoc:
5
6
  # A queue of canned responses
6
7
  class_attribute :responses
7
8
  self.responses = []
8
-
9
+
9
10
  # A default location to use if the responses queue is empty
10
- class_inheritable_accessor :default
11
-
11
+ class_attribute :default
12
+
12
13
  def locate(address)
13
14
  responses.shift || default || Location.new(:street => address)
14
15
  end
@@ -1,6 +1,7 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
-
4
+
4
5
  # freethepostcode.org (http://www.freethepostcode.org/) is a
5
6
  # free service to convert UK postcodes into geolocation data.
6
7
  #
@@ -17,13 +18,13 @@ module Graticule #:nodoc:
17
18
  def locate(postcode)
18
19
  get :postcode => postcode
19
20
  end
20
-
21
+
21
22
  private
22
23
 
23
24
  def prepare_response(response)
24
25
  response.split("\n")[1]
25
26
  end
26
-
27
+
27
28
  def parse_response(response)
28
29
  data = response.split
29
30
  Location.new(:latitude => data[0].to_f, :longitude => data[1].to_f, :precision => :unknown)
@@ -32,7 +33,7 @@ module Graticule #:nodoc:
32
33
  def check_error(response)
33
34
  raise AddressError, 'unknown address' if response.blank?
34
35
  end
35
-
36
+
36
37
  end
37
38
  end
38
39
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
 
@@ -12,9 +13,9 @@ module Graticule #:nodoc:
12
13
  def locate(address)
13
14
  get :locate => address.is_a?(String) ? address : location_from_params(address).to_s(:country => false)
14
15
  end
15
-
16
+
16
17
  private
17
-
18
+
18
19
  class Response
19
20
  include HappyMapper
20
21
  tag 'geodata'
@@ -25,25 +26,25 @@ module Graticule #:nodoc:
25
26
  element :locality, String, :deep => true, :tag => 'city'
26
27
  element :postal_code, String, :tag => 'postal'
27
28
  element :region, String, :deep => true, :tag => 'prov'
28
-
29
+
29
30
  class Error
30
31
  include HappyMapper
31
32
  tag 'error'
32
33
  element :code, Integer
33
34
  element :description, String
34
35
  end
35
-
36
+
36
37
  has_one :error, Error
37
-
38
+
38
39
  def street
39
40
  [street_number, street_name].join(' ')
40
41
  end
41
42
  end
42
-
43
+
43
44
  def prepare_response(xml)
44
45
  Response.parse(xml, :single => true)
45
46
  end
46
-
47
+
47
48
  def parse_response(response) #:nodoc:
48
49
  Location.new(
49
50
  :latitude => response.latitude,
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
 
@@ -27,13 +28,13 @@ module Graticule #:nodoc:
27
28
  def locate(address)
28
29
  get :address => address.is_a?(String) ? address : location_from_params(address).to_s(:country => false)
29
30
  end
30
-
31
+
31
32
  private
32
33
  class Point
33
34
  include HappyMapper
34
35
  tag 'Point'
35
36
  namespace 'http://www.w3.org/2003/01/geo/wgs84_pos#'
36
-
37
+
37
38
  element :description, String, :namespace => 'http://purl.org/dc/elements/1.1/'
38
39
  element :longitude, Float, :tag => 'long'
39
40
  element :latitude, Float, :tag => 'lat'
@@ -1,30 +1,31 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
  class Geonames < Base
4
-
5
+
5
6
  def initialize
6
7
  @url = URI.parse 'http://ws.geonames.org/timezone'
7
8
  end
8
-
9
+
9
10
  def time_zone(location)
10
- get :formatted => 'true', :style => 'full', :lat => location.latitude, :lng => location.longitude
11
+ get :formatted => 'true', :style => 'full', :lat => location.latitude, :lng => location.longitude
11
12
  end
12
-
13
- private
13
+
14
+ private
14
15
  class Status
15
16
  include HappyMapper
16
17
  tag 'status'
17
18
  attribute :message, String
18
19
  attribute :value, String
19
20
  end
20
-
21
+
21
22
  class Response
22
23
  include HappyMapper
23
24
  tag 'geonames'
24
25
  element :timezoneId, String, :deep => true
25
26
  has_one :status, Status
26
27
  end
27
-
28
+
28
29
  def prepare_response(xml)
29
30
  Response.parse(xml, :single => true)
30
31
  end
@@ -32,7 +33,7 @@ module Graticule #:nodoc:
32
33
  def parse_response(response) #:nodoc:
33
34
  response.timezoneId
34
35
  end
35
-
36
+
36
37
  # Extracts and raises an error from +xml+, if any.
37
38
  def check_error(response) #:nodoc:
38
39
  if response && response.status
@@ -1,9 +1,10 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
-
4
+
4
5
  # First you need a Google Maps API key. You can register for one here:
5
6
  # http://www.google.com/apis/maps/signup.html
6
- #
7
+ #
7
8
  # gg = Graticule.service(:google).new(MAPS_API_KEY)
8
9
  # location = gg.locate '1600 Amphitheater Pkwy, Mountain View, CA'
9
10
  # p location.coordinates
@@ -11,7 +12,7 @@ module Graticule #:nodoc:
11
12
  #
12
13
  class Google < Base
13
14
  # http://www.google.com/apis/maps/documentation/#Geocoding_HTTP_Request
14
-
15
+
15
16
  # http://www.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
16
17
  PRECISION = {
17
18
  0 => Precision::Unknown, # Unknown location.
@@ -44,15 +45,15 @@ module Graticule #:nodoc:
44
45
 
45
46
  attribute :accuracy, Integer, :tag => 'Accuracy'
46
47
  end
47
-
48
+
48
49
  class Placemark
49
50
  include HappyMapper
50
51
  tag 'Placemark'
51
52
  element :coordinates, String, :deep => true
52
53
  has_one :address, Address
53
-
54
+
54
55
  attr_reader :longitude, :latitude
55
-
56
+
56
57
  with_options :deep => true, :namespace => 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0' do |map|
57
58
  map.element :street, String, :tag => 'ThoroughfareName'
58
59
  map.element :locality, String, :tag => 'LocalityName'
@@ -60,27 +61,27 @@ module Graticule #:nodoc:
60
61
  map.element :postal_code, String, :tag => 'PostalCodeNumber'
61
62
  map.element :country, String, :tag => 'CountryNameCode'
62
63
  end
63
-
64
+
64
65
  def coordinates=(coordinates)
65
66
  @longitude, @latitude, _ = coordinates.split(',').map { |v| v.to_f }
66
67
  end
67
-
68
+
68
69
  def accuracy
69
70
  address.accuracy if address
70
71
  end
71
-
72
+
72
73
  def precision
73
74
  PRECISION[accuracy] || :unknown
74
75
  end
75
76
  end
76
-
77
+
77
78
  class Response
78
79
  include HappyMapper
79
80
  tag 'Response'
80
81
  element :code, Integer, :tag => 'code', :deep => true
81
82
  has_many :placemarks, Placemark
82
83
  end
83
-
84
+
84
85
  def prepare_response(xml)
85
86
  Response.parse(xml, :single => true)
86
87
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'yaml'
2
3
 
3
4
  module Graticule #:nodoc:
@@ -13,14 +14,14 @@ module Graticule #:nodoc:
13
14
  def locate(address)
14
15
  get :ip => address, :position => true
15
16
  end
16
-
17
+
17
18
  private
18
-
19
+
19
20
  def prepare_response(response)
20
21
  # add new line so YAML.load doesn't puke
21
22
  YAML.load(response + "\n")
22
23
  end
23
-
24
+
24
25
  def parse_response(response) #:nodoc:
25
26
  Location.new.tap do |location|
26
27
  location.latitude = response['Latitude']
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
 
@@ -5,20 +6,20 @@ module Graticule #:nodoc:
5
6
  #
6
7
  # See http://emad.fano.us/blog/?p=277
7
8
  class LocalSearchMaps < Base
8
-
9
+
9
10
  def initialize
10
11
  @url = URI.parse 'http://geo.localsearchmaps.com/'
11
12
  end
12
-
13
+
13
14
  # This web service will handle some addresses outside the US
14
15
  # if given more structured arguments than just a string address
15
16
  # So allow input as a hash for the different arguments (:city, :country, :zip)
16
17
  def locate(params)
17
18
  get params.is_a?(String) ? {:loc => params} : map_attributes(location_from_params(params))
18
19
  end
19
-
20
+
20
21
  private
21
-
22
+
22
23
  def map_attributes(location)
23
24
  mapping = {:street => :street, :locality => :city, :region => :state, :postal_code => :zip, :country => :country}
24
25
  mapping.keys.inject({}) do |result,attribute|
@@ -26,7 +27,7 @@ module Graticule #:nodoc:
26
27
  result
27
28
  end
28
29
  end
29
-
30
+
30
31
  def check_error(js)
31
32
  case js
32
33
  when nil
@@ -35,12 +36,12 @@ module Graticule #:nodoc:
35
36
  raise AddressError, 'Location not found'
36
37
  end
37
38
  end
38
-
39
+
39
40
  def parse_response(js)
40
41
  coordinates = js.match(/map.centerAndZoom\(new GPoint\((.+?), (.+?)\)/)
41
42
  Location.new(:longitude => coordinates[1].to_f, :latitude => coordinates[2].to_f)
42
43
  end
43
-
44
+
44
45
  end
45
46
  end
46
47
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
 
@@ -6,10 +7,10 @@ module Graticule #:nodoc:
6
7
  # http://developer.mapquest.com/Home/Register?_devAPISignup_WAR_devAPISignup_action=signup&_devAPISignup_WAR_devAPISignup_clientType=Developer
7
8
  #
8
9
  # mq = Graticule.service(:mapquest).new(CLIENT_ID, PASSWORD)
9
- # location = gg.locate('44 Allen Rd., Lovell, ME 04051')
10
+ # location = gg.locate('44 Allen Rd., Lovell, ME 04051')
10
11
  # [42.78942, -86.104424]
11
12
  #
12
- class Mapquest < Base
13
+ class Mapquest < Base
13
14
  # I would link to the documentation here, but there is none that will do anything but confuse you.
14
15
 
15
16
  PRECISION = {
@@ -48,7 +49,7 @@ module Graticule #:nodoc:
48
49
  url.query = URI.escape(query)
49
50
  url
50
51
  end
51
-
52
+
52
53
  class Address
53
54
  include HappyMapper
54
55
  tag 'GeoAddress'
@@ -60,18 +61,18 @@ module Graticule #:nodoc:
60
61
  element :postal_code, String, :tag => 'PostalCode'
61
62
  element :country, String, :tag => 'AdminArea1'
62
63
  element :result_code, String, :tag => 'ResultCode'
63
-
64
+
64
65
  def precision
65
66
  PRECISION[result_code.to_s[0,2]] || :unknown
66
67
  end
67
68
  end
68
-
69
+
69
70
  class Result
70
71
  include HappyMapper
71
72
  tag 'GeocodeResponse'
72
73
  has_many :addresses, Address, :deep => true
73
74
  end
74
-
75
+
75
76
  def prepare_response(xml)
76
77
  Result.parse(xml, :single => true)
77
78
  end
@@ -1,9 +1,10 @@
1
+ # encoding: UTF-8
1
2
  require 'timeout'
2
3
 
3
4
  module Graticule #:nodoc:
4
5
  module Geocoder #:nodoc:
5
6
  class Multi
6
-
7
+
7
8
  # The Multi geocoder allows you to use multiple geocoders in succession.
8
9
  #
9
10
  # geocoder = Graticule.service(:multi).new(
@@ -30,10 +31,10 @@ module Graticule #:nodoc:
30
31
  #
31
32
  def initialize(*geocoders, &acceptable)
32
33
  @options = {:timeout => 10, :async => false}.merge(geocoders.extract_options!)
33
- @acceptable = acceptable || lambda { true }
34
- @geocoders = geocoders.flatten
34
+ @acceptable = acceptable || Proc.new { true }
35
+ @geocoders = geocoders
35
36
  end
36
-
37
+
37
38
  def locate(address)
38
39
  @lookup = @options[:async] ? ParallelLookup.new : SerialLookup.new
39
40
  last_error = nil
@@ -53,16 +54,16 @@ module Graticule #:nodoc:
53
54
  end
54
55
  @lookup.result || raise(last_error || AddressError.new("Couldn't find '#{address}' with any of the services"))
55
56
  end
56
-
57
+
57
58
  class SerialLookup #:nodoc:
58
59
  def initialize
59
60
  @blocks = []
60
61
  end
61
-
62
+
62
63
  def perform(&block)
63
64
  @blocks << block
64
65
  end
65
-
66
+
66
67
  def result
67
68
  result = nil
68
69
  @blocks.detect do |block|
@@ -71,19 +72,19 @@ module Graticule #:nodoc:
71
72
  result
72
73
  end
73
74
  end
74
-
75
+
75
76
  class ParallelLookup #:nodoc:
76
77
  def initialize
77
78
  @threads = []
78
79
  @monitor = Monitor.new
79
80
  end
80
-
81
+
81
82
  def perform(&block)
82
83
  @threads << Thread.new do
83
84
  self.result = block.call
84
85
  end
85
86
  end
86
-
87
+
87
88
  def result=(result)
88
89
  if result
89
90
  @monitor.synchronize do
@@ -92,7 +93,7 @@ module Graticule #:nodoc:
92
93
  end
93
94
  end
94
95
  end
95
-
96
+
96
97
  def result
97
98
  @threads.each(&:join)
98
99
  @result
@@ -1,14 +1,15 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
4
 
4
5
  # Multimap geocoding API
5
-
6
+
6
7
  class Multimap < Base
7
-
8
+
8
9
  # This precision information is not complete.
9
10
  # More details should be implemented from:
10
11
  # http://www.multimap.com/share/documentation/clientzone/gqcodes.htm
11
-
12
+
12
13
  PRECISION = {
13
14
  6 => Precision::Country,
14
15
  5 => Precision::Region,
@@ -17,39 +18,39 @@ module Graticule #:nodoc:
17
18
  2 => Precision::Street,
18
19
  1 => Precision::Address
19
20
  }
20
-
21
+
21
22
  # Web services initializer.
22
23
  #
23
24
  # The +api_key+ is the Open API key that uniquely identifies your
24
25
  # application.
25
26
  #
26
27
  # See http://www.multimap.com/openapi/
27
-
28
+
28
29
  def initialize(api_key)
29
30
  @api_key = api_key
30
31
  @url = URI.parse "http://clients.multimap.com/API/geocode/1.2/#{@api_key}"
31
32
  end
32
-
33
+
33
34
  # Returns a location for an address in the form of a String, Hash or Location.
34
-
35
+
35
36
  def locate(address)
36
37
  location = address.is_a?(String) ? address : location_from_params(address)
37
38
  case location
38
39
  when String
39
40
  get :qs => location
40
41
  when Location
41
- get "street" => location.street,
42
- "region" => location.region,
43
- "city" => location.locality,
44
- "postalCode" => location.postal_code,
42
+ get "street" => location.street,
43
+ "region" => location.region,
44
+ "city" => location.locality,
45
+ "postalCode" => location.postal_code,
45
46
  "countryCode" => location.country
46
47
  end
47
48
  end
48
-
49
+
49
50
  class Address
50
51
  include HappyMapper
51
52
  tag 'Location'
52
-
53
+
53
54
  attribute :quality, Integer, :tag => 'geocodeQuality'
54
55
  element :street, String, :tag => 'Street', :deep => true
55
56
  element :locality, String, :tag => 'Area', :deep => true
@@ -58,23 +59,23 @@ module Graticule #:nodoc:
58
59
  element :country, String, :tag => 'CountryCode', :deep => true
59
60
  element :latitude, Float, :tag => 'Lat', :deep => true
60
61
  element :longitude, Float, :tag => 'Lon', :deep => true
61
-
62
+
62
63
  def precision
63
64
  PRECISION[quality] || :unknown
64
65
  end
65
66
  end
66
-
67
+
67
68
  class Result
68
69
  include HappyMapper
69
70
  tag 'Results'
70
71
  attribute :error, String, :tag => 'errorCode'
71
72
  has_many :addresses, Address
72
73
  end
73
-
74
+
74
75
  def prepare_response(xml)
75
76
  Result.parse(xml, :single => true)
76
77
  end
77
-
78
+
78
79
  def parse_response(result)
79
80
  addr = result.addresses.first
80
81
  Location.new(
@@ -88,11 +89,11 @@ module Graticule #:nodoc:
88
89
  :precision => addr.precision
89
90
  )
90
91
  end
91
-
92
+
92
93
  def check_error(result)
93
94
  raise Error, result.error unless result.error.blank?
94
95
  end
95
-
96
+
96
97
  end
97
98
  end
98
99
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'json'
2
3
 
3
4
  module Graticule
@@ -1,6 +1,7 @@
1
+ # encoding: UTF-8
1
2
  module Graticule #:nodoc:
2
3
  module Geocoder #:nodoc:
3
-
4
+
4
5
  # Yahoo geocoding API.
5
6
  #
6
7
  # http://developer.yahoo.com/maps/rest/V1/geocode.html
@@ -42,13 +43,13 @@ module Graticule #:nodoc:
42
43
  # yahoo pukes on line breaks
43
44
  get :location => location.gsub("\n", ', ')
44
45
  end
45
-
46
+
46
47
  private
47
-
48
+
48
49
  class Address
49
50
  include HappyMapper
50
51
  tag 'Result'
51
-
52
+
52
53
  attribute :precision, String
53
54
  attribute :warning, String
54
55
  element :latitude, Float, :tag => 'Latitude'
@@ -58,24 +59,24 @@ module Graticule #:nodoc:
58
59
  element :region, String, :tag => 'State'
59
60
  element :postal_code, String, :tag => 'Zip'
60
61
  element :country, String, :tag => 'Country'
61
-
62
+
62
63
  def precision
63
64
  PRECISION[@precision] || :unknown
64
65
  end
65
66
  end
66
-
67
+
67
68
  class Result
68
69
  include HappyMapper
69
70
  tag 'ResultSet'
70
71
  has_many :addresses, Address
71
72
  end
72
-
73
+
73
74
  class Error
74
75
  include HappyMapper
75
76
  tag 'Error'
76
77
  element :message, String, :tag => 'Message'
77
78
  end
78
-
79
+
79
80
  def parse_response(response) # :nodoc:
80
81
  addr = Result.parse(response, :single => true).addresses.first
81
82
  Location.new(
@@ -108,6 +109,6 @@ module Graticule #:nodoc:
108
109
  end
109
110
 
110
111
  end
111
-
112
+
112
113
  end
113
114
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
3
 
3
4
  # A geographic location
@@ -9,7 +10,7 @@ module Graticule
9
10
 
10
11
  def initialize(attrs = {})
11
12
  attrs.each do |key,value|
12
- self.send("#{key}=", value)
13
+ self.send("#{key}=", value.respond_to?(:force_encoding) ? value.force_encoding('UTF-8') : value)
13
14
  end
14
15
  self.precision ||= :unknown
15
16
  end
@@ -1,10 +1,11 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
-
3
+
3
4
  # Used to compare the precision of different geocoded locations
4
5
  class Precision
5
6
  include Comparable
6
7
  attr_reader :name
7
-
8
+
8
9
  NAMES = [
9
10
  :unknown,
10
11
  :country,
@@ -15,12 +16,12 @@ module Graticule
15
16
  :address,
16
17
  :premise
17
18
  ]
18
-
19
+
19
20
  def initialize(name)
20
21
  @name = name.to_sym
21
22
  raise ArgumentError, "#{name} is not a valid precision. Use one of #{NAMES.inspect}" unless NAMES.include?(@name)
22
23
  end
23
-
24
+
24
25
  Unknown = Precision.new(:unknown)
25
26
  Country = Precision.new(:country)
26
27
  Region = Precision.new(:region)
@@ -29,16 +30,16 @@ module Graticule
29
30
  Street = Precision.new(:street)
30
31
  Address = Precision.new(:address)
31
32
  Premise = Precision.new(:premise)
32
-
33
+
33
34
  def to_s
34
35
  @name.to_s
35
36
  end
36
-
37
+
37
38
  def <=>(other)
38
39
  other = Precision.new(other) unless other.is_a?(Precision)
39
40
  NAMES.index(self.name) <=> NAMES.index(other.name)
40
41
  end
41
-
42
+
42
43
  def ==(other)
43
44
  (self <=> other) == 0
44
45
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module Graticule
2
- VERSION = '2.0.1' unless defined?(::Graticule::VERSION)
3
+ VERSION = '2.1.0' unless defined?(::Graticule::VERSION)
3
4
  end
metadata CHANGED
@@ -1,119 +1,92 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: graticule
3
- version: !ruby/object:Gem::Version
4
- hash: 13
5
- prerelease: false
6
- segments:
7
- - 2
8
- - 0
9
- - 1
10
- version: 2.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.1.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Brandon Keepers
14
9
  - Daniel Morrison
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-02-28 00:00:00 -05:00
20
- default_executable: geocode
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
13
+ date: 2011-08-05 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: &70239866982580 !ruby/object:Gem::Requirement
24
18
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
32
- requirement: *id001
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
33
23
  type: :runtime
34
- name: activesupport
35
24
  prerelease: false
36
- - !ruby/object:Gem::Dependency
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *70239866982580
26
+ - !ruby/object:Gem::Dependency
27
+ name: i18n
28
+ requirement: &70239866981940 !ruby/object:Gem::Requirement
38
29
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- requirement: *id002
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
47
34
  type: :runtime
48
- name: i18n
49
35
  prerelease: false
50
- - !ruby/object:Gem::Dependency
51
- version_requirements: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *70239866981940
37
+ - !ruby/object:Gem::Dependency
38
+ name: happymapper
39
+ requirement: &70239866981260 !ruby/object:Gem::Requirement
52
40
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 19
57
- segments:
58
- - 0
59
- - 3
60
- - 0
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
61
44
  version: 0.3.0
62
- requirement: *id003
63
45
  type: :runtime
64
- name: happymapper
65
46
  prerelease: false
66
- - !ruby/object:Gem::Dependency
67
- version_requirements: &id004 !ruby/object:Gem::Requirement
47
+ version_requirements: *70239866981260
48
+ - !ruby/object:Gem::Dependency
49
+ name: json
50
+ requirement: &70239866980440 !ruby/object:Gem::Requirement
68
51
  none: false
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- hash: 3
73
- segments:
74
- - 0
75
- version: "0"
76
- requirement: *id004
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
77
56
  type: :runtime
78
- name: json
79
57
  prerelease: false
80
- - !ruby/object:Gem::Dependency
81
- version_requirements: &id005 !ruby/object:Gem::Requirement
58
+ version_requirements: *70239866980440
59
+ - !ruby/object:Gem::Dependency
60
+ name: mocha
61
+ requirement: &70239866979600 !ruby/object:Gem::Requirement
82
62
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- hash: 3
87
- segments:
88
- - 0
89
- version: "0"
90
- requirement: *id005
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
91
67
  type: :development
92
- name: mocha
93
68
  prerelease: false
94
- - !ruby/object:Gem::Dependency
95
- version_requirements: &id006 !ruby/object:Gem::Requirement
69
+ version_requirements: *70239866979600
70
+ - !ruby/object:Gem::Dependency
71
+ name: rcov
72
+ requirement: &70239866978740 !ruby/object:Gem::Requirement
96
73
  none: false
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- hash: 3
101
- segments:
102
- - 0
103
- version: "0"
104
- requirement: *id006
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
105
78
  type: :development
106
- name: rcov
107
79
  prerelease: false
108
- description: Graticule is a geocoding API that provides a common interface to all the popular services, including Google, Yahoo, Geocoder.us, and MetaCarta.
80
+ version_requirements: *70239866978740
81
+ description: Graticule is a geocoding API that provides a common interface to all
82
+ the popular services, including Google, Yahoo, Geocoder.us, and MetaCarta.
109
83
  email: brandon@opensoul.org
110
- executables:
84
+ executables:
111
85
  - geocode
112
86
  extensions: []
113
-
114
- extra_rdoc_files:
87
+ extra_rdoc_files:
115
88
  - README.textile
116
- files:
89
+ files:
117
90
  - bin/geocode
118
91
  - lib/graticule/cli.rb
119
92
  - lib/graticule/core_ext.rb
@@ -143,42 +116,38 @@ files:
143
116
  - CHANGELOG.txt
144
117
  - LICENSE.txt
145
118
  - README.textile
146
- has_rdoc: true
147
119
  homepage: http://github.com/collectiveidea/graticule
148
120
  licenses: []
149
-
150
121
  post_install_message:
151
- rdoc_options:
122
+ rdoc_options:
152
123
  - --main
153
124
  - README.rdoc
154
125
  - --inline-source
155
126
  - --line-numbers
156
- require_paths:
127
+ require_paths:
157
128
  - lib
158
- required_ruby_version: !ruby/object:Gem::Requirement
129
+ required_ruby_version: !ruby/object:Gem::Requirement
159
130
  none: false
160
- requirements:
161
- - - ">="
162
- - !ruby/object:Gem::Version
163
- hash: 3
164
- segments:
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ segments:
165
136
  - 0
166
- version: "0"
167
- required_rubygems_version: !ruby/object:Gem::Requirement
137
+ hash: -334130965420677482
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
139
  none: false
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- hash: 3
173
- segments:
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ segments:
174
145
  - 0
175
- version: "0"
146
+ hash: -334130965420677482
176
147
  requirements: []
177
-
178
148
  rubyforge_project: graticule
179
- rubygems_version: 1.3.7
149
+ rubygems_version: 1.8.6
180
150
  signing_key:
181
151
  specification_version: 3
182
152
  summary: API for using all the popular geocoding services.
183
153
  test_files: []
184
-