jonleighton-geoplanet 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,125 @@
1
+ = geoplanet
2
+
3
+ A Ruby wrapper for the Yahoo! GeoPlanet APIs. It's inspired on Mattt Thompson's yahoo-geoplanet gem,
4
+ but this version supports better usage of matrix and query parameters, uses JSON for API communication to minimize bandwidth usage, supports both short & long versions of a place, and supports multiple languages.
5
+
6
+ == Usage
7
+
8
+ === Searching for a Location:
9
+
10
+ require 'geoplanet'
11
+ GeoPlanet.appid = [Your App ID Here]
12
+
13
+ # Search for places that matches "Springfield" (the API returns 1 by default)
14
+ GeoPlanet::Place.search("Springfield")
15
+
16
+ # Search for *all* places that matches "Springfield"
17
+ GeoPlanet::Place.search("Springfield", :count => 0)
18
+
19
+ # You can pass in any Matrix or Query parameters this way too
20
+ # For more details see the following URLs:
21
+ # http://developer.yahoo.com/geo/guide/resources_and_collections.html#matrix_parameters
22
+ # http://developer.yahoo.com/geo/guide/resources_and_collections.html#query_parameters
23
+
24
+ === Initializing by Where On Earth ID && Associations
25
+
26
+ require 'geoplanet'
27
+ GeoPlanet.appid = [Your App ID Here]
28
+
29
+ a = GeoPlanet::Place.new(752067) # WoE ID for Algeciras
30
+
31
+ # Everything you get back from the API you have direct access to
32
+ # through the Place object. For example:
33
+
34
+ a.version # "long"
35
+ a.placetype # "Town"
36
+ a.placetype_code # 7
37
+ a.admin1 # "Andalucia"
38
+ a.admin1_code # "ES-AN"
39
+ a.admin1_placetype # "Autonomous Community"
40
+ a.admin2 # "Cadiz"
41
+ a.admin2_code # ""
42
+ a.admin2_placetype # "Province"
43
+ a.latitude # 36.127602
44
+ # Latitude and Longitude are values at Centroid
45
+ a.bounding_box # [[36.109779, -5.47725], [36.164268, -5.43527]]
46
+ # Bounding box are SW / NE coordinates in array
47
+
48
+ # We unlock the true power of GeoPlanet with association collections
49
+ # Check out this truly amazing stuff:
50
+
51
+ # A list of other towns in the area
52
+ a.siblings
53
+
54
+ # A complete hierarchy, from country down to municipality
55
+ a.ancestors
56
+
57
+ # Postal Codes at Algeciras
58
+ a.children(:select => "long", :type => 11)
59
+
60
+ # You can use multiple types on the same query.
61
+ # e.g. Country and Province for Algeciras
62
+ a.belongtos(:type => [12, 9])
63
+
64
+ # You can specify the language you want for the results.
65
+ a.belongtos(:type => 12, :lang => 'es_ES').first.name # España
66
+
67
+ a = GeoPlanet::Place.new(752067, :lang => :es)
68
+ a.country # España
69
+
70
+ # It is also possible to query for any association directly using a WOE ID, without
71
+ # create a Place object. Append a '_of' suffix to the association name to build the
72
+ # method name to execute. The first argument is the WOE ID.
73
+
74
+ GeoPlanet::Place.belongtos_of(752067, :type => [12, 9])
75
+
76
+ === Debug Mode
77
+
78
+ If you want to look at the requests that are being executed against the Yahoo GeoPlanet API, you can enable the debug mode. It uses the standard output.
79
+
80
+ GeoPlanet.debug = true
81
+ GeoPlanet::Place.new(752067, :lang => :es)
82
+ # outputs:
83
+ # Yahoo GeoPlanet: GET http://where.yahooapis.com/v1/place/752067?appid=[your_appid]&format=json&lang=es
84
+
85
+
86
+ == REQUIREMENTS:
87
+
88
+ To use this library, you must have a valid Yahoo! App ID.
89
+ You can get one at http://developer.yahoo.com/wsregapp/
90
+
91
+ Additionally, geoplanet has the following gem dependencies:
92
+
93
+ * rest-client >= 0.9
94
+ * json >= 1.1.3
95
+
96
+ == INSTALL:
97
+
98
+ * gem install carlosparamio-geoplanet --source http://gems.github.com
99
+
100
+ == LICENSE:
101
+
102
+ (The MIT License)
103
+
104
+ Copyright (c) 2009 Carlos Paramio
105
+
106
+ Permission is hereby granted, free of charge, to any person obtaining
107
+ a copy of this software and associated documentation files (the
108
+ 'Software'), to deal in the Software without restriction, including
109
+ without limitation the rights to use, copy, modify, merge, publish,
110
+ distribute, sublicense, and/or sell copies of the Software, and to
111
+ permit persons to whom the Software is furnished to do so, subject to
112
+ the following conditions:
113
+
114
+ The above copyright notice and this permission notice shall be
115
+ included in all copies or substantial portions of the Software.
116
+
117
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
118
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
119
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
120
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
121
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
122
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
123
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
124
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
125
+ >>>>>>> 17a1cb2... Use ActiveSupport::JSON instead of JSON if available:README.rdoc
data/geoplanet.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "geoplanet"
3
+ s.version = "0.2.2"
4
+ s.date = "2009-03-23"
5
+ s.summary = "A Ruby wrapper for the Yahoo! GeoPlanet API."
6
+ s.email = "carlosparamio@gmail.com"
7
+ s.homepage = "http://github.com/carlosparamio/geoplanet/"
8
+ s.description = "A Ruby wrapper for the Yahoo! GeoPlanet API.
9
+ It uses JSON format by default to minimize bandwidth usage.
10
+ See http://developer.yahoo.com/geo/ for more information about the API."
11
+ s.authors = ["Carlos Paramio"]
12
+
13
+ s.files = [
14
+ "README.rdoc",
15
+ "geoplanet.gemspec",
16
+ "lib/geoplanet.rb",
17
+ "lib/geoplanet/base.rb",
18
+ "lib/geoplanet/place.rb",
19
+ "lib/geoplanet/version.rb"
20
+ ]
21
+
22
+ s.add_dependency("rest-client", [">= 0.9"])
23
+ s.add_dependency("json", [">= 1.1.3"])
24
+
25
+ s.has_rdoc = false
26
+ s.rdoc_options = ["--main", "README.rdoc"]
27
+ end
data/lib/geoplanet.rb ADDED
@@ -0,0 +1,18 @@
1
+ %w{rubygems rest_client json}.each { |x| require x }
2
+
3
+ require 'geoplanet/version'
4
+ require 'geoplanet/base'
5
+ require 'geoplanet/place'
6
+
7
+ module GeoPlanet
8
+ API_VERSION = "v1"
9
+ API_URL = "http://where.yahooapis.com/#{API_VERSION}/"
10
+
11
+ class << self
12
+ attr_accessor :appid, :debug
13
+ end
14
+
15
+ class BadRequest < StandardError; end
16
+ class NotFound < StandardError; end
17
+ class NotAcceptable < StandardError; end
18
+ end
@@ -0,0 +1,76 @@
1
+ module GeoPlanet
2
+ class Base
3
+ class << self
4
+ def build_url(resource_path, options = {})
5
+ check_options_for(resource_path, options)
6
+
7
+ filters = extract_filters(options)
8
+ matrix_params = extract_matrix_params(options)
9
+ query_params = extract_query_params(options)
10
+
11
+ query_params[:appid] ||= GeoPlanet.appid # use default appid if not provided
12
+
13
+ raise ArgumentError, "appid or q filter missing" if query_params[:appid].nil? || resource_path == 'places' && filters[:q].nil? # required
14
+
15
+ q = ".q('#{filters[:q]}')" if filters[:q]
16
+ type = ".type('#{filters[:type]}')" if filters[:type]
17
+
18
+ query_string = q && type ? "$and(#{q},#{type})" : "#{q}#{type}"
19
+
20
+ matrix_params = ";#{matrix_params.map{|k,v| "#{k}=#{v}"}.join(';')}" if matrix_params.any?
21
+ query_params = "?#{query_params.map{|k,v| "#{k}=#{v}"}.join('&')}" if query_params.any?
22
+
23
+ query_string += "#{matrix_params}#{query_params}"
24
+
25
+ "#{GeoPlanet::API_URL}#{resource_path}#{query_string}"
26
+ end
27
+
28
+ def get(url)
29
+ RestClient.get(url)
30
+ rescue RestClient::RequestFailed
31
+ raise BadRequest, "appid, q filter or format invalid"
32
+ rescue RestClient::ResourceNotFound
33
+ raise NotFound, "woeid or URI invalid"
34
+ end
35
+
36
+ protected
37
+ def supported_options_for(resource_path)
38
+ case resource_path
39
+ when 'places'
40
+ %w(q type start count lang format callback select appid)
41
+ when /^place\/\d+\/parent$/, /^place\/\d+\/ancestors$/, /^place\/\d+$/, 'placetype'
42
+ %w(lang format callback select appid)
43
+ when /^place\/\d+\/belongtos$/, /^place\/\d+\/children$/, 'placetypes'
44
+ %w(type start count lang format callback select appid)
45
+ when /^place\/\d+\/neighbors$/, /^place\/\d+\/siblings$/
46
+ %w(start count lang format callback select appid)
47
+ else
48
+ raise NotFound, "URI invalid"
49
+ end
50
+ end
51
+
52
+ def check_options_for(resource_path, options)
53
+ supported = supported_options_for(resource_path)
54
+ unless options.keys.all?{|o| supported.include?(o.to_s)}
55
+ raise ArgumentError, "invalid option(s) for #{resource_path}. Supported are: #{supported.join(', ')}. You used: #{options.keys.join(', ')}"
56
+ end
57
+ end
58
+
59
+ def extract_filters(options)
60
+ filters = %w(q type)
61
+ options[:type] = options[:type].join(",") if options[:type].is_a?(Array)
62
+ Hash[*(options.select{|k,v| filters.include?(k.to_s)}).flatten]
63
+ end
64
+
65
+ def extract_matrix_params(options)
66
+ matrix_params = %w(start count)
67
+ Hash[*(options.select{|k,v| matrix_params.include?(k.to_s)}).flatten]
68
+ end
69
+
70
+ def extract_query_params(options)
71
+ query_params = %w(lang format callback select appid)
72
+ Hash[*(options.select{|k,v| query_params.include?(k.to_s)}).flatten]
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,119 @@
1
+ module GeoPlanet
2
+ class Place < Base
3
+ attr_reader :version # short or long
4
+ # short
5
+ attr_reader :woeid, :placetype, :placetype_code, :name, :uri, :lang
6
+ # long
7
+ attr_reader :country, :country_code, :postal
8
+ attr_reader :latitude, :longitude, :bounding_box
9
+ attr_reader :admin1, :admin1_code, :admin1_placetype
10
+ attr_reader :admin2, :admin2_code, :admin2_placetype
11
+ attr_reader :admin3, :admin3_code, :admin3_placetype
12
+ attr_reader :locality1, :locality1_placetype
13
+ attr_reader :locality2, :locality2_placetype
14
+ alias_method :lat, :latitude
15
+ alias_method :lon, :longitude
16
+
17
+ # Class methods
18
+ def self.search(text, options = {})
19
+ text = URI.encode(text)
20
+ url = build_url('places', options.merge(:q => text, :format => 'json'))
21
+ puts "Yahoo GeoPlanet: GET #{url}" if GeoPlanet.debug
22
+ get_then_parse(url)
23
+ end
24
+
25
+ def self.get_then_parse(url)
26
+ results = JSON.parse get(url)
27
+ return results['places']['place'].map{|attrs| Place.new attrs} if results['places']
28
+ return Place.new(results['place']) if results['place']
29
+ nil
30
+ rescue
31
+ nil
32
+ end
33
+
34
+ %w(parent ancestors belongtos neighbors siblings children).each do |association|
35
+ self.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
36
+ def self.#{association}_of(woeid, options = {})
37
+ url = build_url("place/\#{woeid}/#{association}", options.merge(:format => "json"))
38
+ puts "Yahoo GeoPlanet: GET \#{url}" if GeoPlanet.debug
39
+ get_then_parse(url)
40
+ end
41
+ RUBY
42
+ end
43
+
44
+ # Instance methods
45
+ def initialize(woe_or_attrs, options = {})
46
+ case woe_or_attrs
47
+ when Integer then initialize_with_woe(woe_or_attrs, options)
48
+ when Hash then initialize_with_attrs(woe_or_attrs)
49
+ else
50
+ raise ArgumentError
51
+ end
52
+ end
53
+
54
+ def initialize_with_woe(woe, options = {})
55
+ url = self.class.build_url("place/#{woe}", options.merge(:format => "json"))
56
+ puts "Yahoo GeoPlanet: GET #{url}" if GeoPlanet.debug
57
+ initialize_with_attrs JSON.parse(Place.get(url))['place']
58
+ end
59
+
60
+
61
+ def initialize_with_attrs(attrs)
62
+ @version = attrs['centroid'] ? 'long' : 'short'
63
+
64
+ # short
65
+ @woeid = attrs['woeid']
66
+ @placetype = attrs['placeTypeName']
67
+ @placetype_code = attrs['placeTypeName attrs']['code']
68
+ @name = attrs['name']
69
+ @uri = attrs['uri']
70
+ @lang = attrs['lang']
71
+
72
+ if version == 'long'
73
+ # long
74
+ @latitude = attrs['centroid']['latitude']
75
+ @longitude = attrs['centroid']['longitude']
76
+ @bounding_box = [ [ attrs['boundingBox']['southWest']['latitude'],
77
+ attrs['boundingBox']['southWest']['longitude'] ],
78
+ [ attrs['boundingBox']['northEast']['latitude'],
79
+ attrs['boundingBox']['northEast']['longitude'] ],
80
+ ]
81
+ @country = attrs['country']
82
+ @country_code = attrs['country attrs']['code'] rescue nil
83
+ @postal = attrs['postal']
84
+ @admin1 = attrs['admin1']
85
+ @admin1_code = attrs['admin1 attrs']['code'] rescue nil
86
+ @admin1_placetype = attrs['admin1 attrs']['type'] rescue nil
87
+ @admin2 = attrs['admin2']
88
+ @admin2_code = attrs['admin2 attrs']['code'] rescue nil
89
+ @admin2_placetype = attrs['admin2 attrs']['type'] rescue nil
90
+ @admin3 = attrs['admin3']
91
+ @admin3_code = attrs['admin3 attrs']['code'] rescue nil
92
+ @admin3_placetype = attrs['admin3 attrs']['type'] rescue nil
93
+ @locality1 = attrs['locality1']
94
+ @locality1_placetype = attrs['locality1 attrs']['type'] rescue nil
95
+ @locality2 = attrs['locality2']
96
+ @locality2_placetype = attrs['locality2 attrs']['type'] rescue nil
97
+ end
98
+ self
99
+ end
100
+
101
+ # Association Collections
102
+ %w(parent ancestors belongtos neighbors siblings children).each do |association|
103
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
104
+ def #{association}(options = {})
105
+ Place.send("#{association}_of", self.woeid, options)
106
+ end
107
+ RUBY
108
+ end
109
+
110
+ def to_s
111
+ self.name
112
+ end
113
+
114
+ def to_i
115
+ self.woeid.to_i
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,8 @@
1
+ module GeoPlanet
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 2
6
+ STRING = [MAJOR, MINOR, TINY].join('.')
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jonleighton-geoplanet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Carlos Paramio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-23 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rest-client
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0.9"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.3
34
+ version:
35
+ description: A Ruby wrapper for the Yahoo! GeoPlanet API. It uses JSON format by default to minimize bandwidth usage. See http://developer.yahoo.com/geo/ for more information about the API.
36
+ email: carlosparamio@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - README.rdoc
45
+ - geoplanet.gemspec
46
+ - lib/geoplanet.rb
47
+ - lib/geoplanet/base.rb
48
+ - lib/geoplanet/place.rb
49
+ - lib/geoplanet/version.rb
50
+ has_rdoc: false
51
+ homepage: http://github.com/carlosparamio/geoplanet/
52
+ licenses:
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.3.5
75
+ signing_key:
76
+ specification_version: 2
77
+ summary: A Ruby wrapper for the Yahoo! GeoPlanet API.
78
+ test_files: []
79
+