geoplanet 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +132 -0
- data/geoplanet.gemspec +25 -0
- data/lib/geoplanet.rb +29 -0
- data/lib/geoplanet/base.rb +76 -0
- data/lib/geoplanet/place.rb +119 -0
- data/lib/geoplanet/version.rb +8 -0
- metadata +80 -0
data/README.rdoc
ADDED
@@ -0,0 +1,132 @@
|
|
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
|
+
Please note that if you have ActiveSupport::JSON defined (either by
|
97
|
+
manually having loaded it or when you use geoplanet within a Rails
|
98
|
+
application) the json dependency will be ignored and geoplanet uses
|
99
|
+
ActiveSupport::JSON instead.
|
100
|
+
|
101
|
+
== INSTALL:
|
102
|
+
|
103
|
+
gem install carlosparamio-geoplanet --source http://gems.github.com
|
104
|
+
|
105
|
+
== LICENSE:
|
106
|
+
|
107
|
+
(The MIT License)
|
108
|
+
|
109
|
+
Copyright (c) 2009 Carlos Paramio
|
110
|
+
|
111
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
112
|
+
a copy of this software and associated documentation files (the
|
113
|
+
'Software'), to deal in the Software without restriction, including
|
114
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
115
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
116
|
+
permit persons to whom the Software is furnished to do so, subject to
|
117
|
+
the following conditions:
|
118
|
+
|
119
|
+
The above copyright notice and this permission notice shall be
|
120
|
+
included in all copies or substantial portions of the Software.
|
121
|
+
|
122
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
123
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
124
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
125
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
126
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
127
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
128
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
129
|
+
|
130
|
+
== CONTRIBUTORS:
|
131
|
+
|
132
|
+
Nielsomat <http://github.com/Nielsomat> : Usage of ActiveSupport::JSON when available
|
data/geoplanet.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "geoplanet"
|
3
|
+
s.version = "0.2.2"
|
4
|
+
s.date = "2009-04-01"
|
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. It uses JSON format by default to minimize bandwidth usage. See http://developer.yahoo.com/geo/ for more information about the API."
|
9
|
+
s.authors = ["Carlos Paramio"]
|
10
|
+
|
11
|
+
s.files = [
|
12
|
+
"README.rdoc",
|
13
|
+
"geoplanet.gemspec",
|
14
|
+
"lib/geoplanet.rb",
|
15
|
+
"lib/geoplanet/base.rb",
|
16
|
+
"lib/geoplanet/place.rb",
|
17
|
+
"lib/geoplanet/version.rb"
|
18
|
+
]
|
19
|
+
|
20
|
+
s.add_dependency("rest-client", [">= 0.9"])
|
21
|
+
s.add_dependency("json", [">= 1.1.3"])
|
22
|
+
|
23
|
+
s.has_rdoc = false
|
24
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
25
|
+
end
|
data/lib/geoplanet.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
%w{rubygems rest_client}.each { |x| require x }
|
2
|
+
|
3
|
+
if defined?(ActiveSupport::JSON)
|
4
|
+
JSON = ActiveSupport::JSON
|
5
|
+
module JSON
|
6
|
+
def self.parse(json)
|
7
|
+
decode(json)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
else
|
11
|
+
require 'json'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'geoplanet/version'
|
15
|
+
require 'geoplanet/base'
|
16
|
+
require 'geoplanet/place'
|
17
|
+
|
18
|
+
module GeoPlanet
|
19
|
+
API_VERSION = "v1"
|
20
|
+
API_URL = "http://where.yahooapis.com/#{API_VERSION}/"
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_accessor :appid, :debug
|
24
|
+
end
|
25
|
+
|
26
|
+
class BadRequest < StandardError; end
|
27
|
+
class NotFound < StandardError; end
|
28
|
+
class NotAcceptable < StandardError; end
|
29
|
+
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
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 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-04-01 00:00:00 +02: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: true
|
51
|
+
homepage: http://github.com/carlosparamio/geoplanet/
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --main
|
57
|
+
- README.rdoc
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.5
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: A Ruby wrapper for the Yahoo! GeoPlanet API.
|
79
|
+
test_files: []
|
80
|
+
|