yahoo-geoplanet 0.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.
@@ -0,0 +1,3 @@
1
+ == 0.1.0 2008-10-08
2
+
3
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Mattt Thompson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ PostInstall.txt
5
+ README.txt
6
+ Rakefile
7
+ config/hoe.rb
8
+ config/requirements.rb
9
+ lib/rest.rb
10
+ lib/yahoo-geoplanet.rb
11
+ lib/yahoo-geoplanet/base.rb
12
+ lib/yahoo-geoplanet/place.rb
13
+ lib/yahoo-geoplanet/version.rb
14
+ script/console
15
+ script/destroy
16
+ script/generate
17
+ script/txt2html
18
+ setup.rb
19
+ tasks/deployment.rake
20
+ tasks/environment.rake
21
+ tasks/website.rake
File without changes
@@ -0,0 +1,91 @@
1
+ = yahoo-geoplanet
2
+
3
+ A Ruby wrapper for the Yahoo! GeoPlanet APIs.
4
+
5
+ == Example Usage
6
+
7
+ === Searching for a Location:
8
+
9
+ require 'yahoo-geoplanet'
10
+ include Yahoo::GeoPlanet
11
+ Yahoo::GeoPlanet.app_id = [Your App ID Here]
12
+
13
+ # Returns first 20 results by default
14
+ Place.search("Springfield")
15
+
16
+ # ...but let's say you want _all_ of them
17
+ Place.search("Springfield", :count => 0) # Returns all 110
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 'yahoo-geoplanet'
27
+ include Yahoo::GeoPlanet
28
+ Yahoo::GeoPlanet.app_id = [Your App ID Here]
29
+
30
+ cmu = Place.new(23511275) # WoE ID for Carnegie Mellon University
31
+
32
+ # Everything you get back from the API you have direct access to
33
+ # through the Place object. For example:
34
+
35
+ puts cmu.type # "Point of Interest"
36
+ puts cmu.county # "Allegheny"
37
+ puts cmu.latitude # 40.444
38
+ # Latitude and Longitude are values at Centroid
39
+ puts cmu.bounding_box # [[40.44445, -79.943314], [40.44355, -79.944511]]
40
+ # Bounding box are NW / SE coordinates in array
41
+
42
+ # We unlock the true power of GeoPlanet with association collections
43
+ # Check out this truly amazing stuff:
44
+
45
+ # The containing GeoPlanet entity for CMU
46
+ puts cmu.parent # "Squirrel Hill North"
47
+
48
+ # A list of other points of interest in the area
49
+ cmu.siblings.each{|s| puts s}
50
+
51
+ # A complete hierarchy, from country down to suburb
52
+ cmu.ancestors.each{|s| puts s}
53
+
54
+ == REQUIREMENTS:
55
+
56
+ To use this library, you must have a valid Yahoo! App ID.
57
+ You can get one at http://developer.yahoo.com/wsregapp/
58
+
59
+ Additionally, yahoo-geoplanet has the following gem dependencies:
60
+
61
+ * Hpricot >= 0.6
62
+ * ActiveSupport >= 2.1.0
63
+
64
+ == INSTALL:
65
+
66
+ * sudo gem install yahoo-geoplanet
67
+
68
+ == LICENSE:
69
+
70
+ (The MIT License)
71
+
72
+ Copyright (c) 2008 Mattt Thompson
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ 'Software'), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
88
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
89
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
90
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
91
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,75 @@
1
+ require 'yahoo-geoplanet/version'
2
+
3
+ AUTHOR = "Mattt Thompson"
4
+ EMAIL = "mail@matttthompson.com"
5
+ DESCRIPTION = "yahoo-geoplanet is a wrapper to the Y! GeoPlanet REST APIs"
6
+ GEM_NAME = 'yahoo-geoplanet' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'yahoo-geoplanet' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ ['hpricot', '>= 0.6'],
12
+ ['activesupport', '>= 2.1.0'],
13
+ ['flexmock', '>= 0.8.2']
14
+ ] # An array of rubygem dependencies [name, version]
15
+
16
+ @config_file = "~/.rubyforge/user-config.yml"
17
+ @config = nil
18
+ RUBYFORGE_USERNAME = "mattt"
19
+ def rubyforge_username
20
+ unless @config
21
+ begin
22
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
23
+ rescue
24
+ puts <<-EOS
25
+ ERROR: No rubyforge config file found: #{@config_file}
26
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
27
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
28
+ EOS
29
+ exit
30
+ end
31
+ end
32
+ RUBYFORGE_USERNAME.replace @config["username"]
33
+ end
34
+
35
+
36
+ REV = nil
37
+ # UNCOMMENT IF REQUIRED:
38
+ # REV = YAML.load(`svn info`)['Revision']
39
+ VERS = Yahoo::GeoPlanet::VERSION::STRING + (REV ? ".#{REV}" : "")
40
+ RDOC_OPTS = ['--quiet', '--title', 'yahoo-geoplanet documentation',
41
+ "--opname", "index.html",
42
+ "--line-numbers",
43
+ "--main", "README",
44
+ "--inline-source"]
45
+
46
+ class Hoe
47
+ def extra_deps
48
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
49
+ @extra_deps
50
+ end
51
+ end
52
+
53
+ # Generate all the Rake tasks
54
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
55
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
56
+ p.developer(AUTHOR, EMAIL)
57
+ p.description = DESCRIPTION
58
+ p.summary = DESCRIPTION
59
+ p.url = HOMEPATH
60
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
61
+ p.test_globs = ["test/**/test_*.rb"]
62
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
63
+
64
+ # == Optional
65
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
66
+ #p.extra_deps = EXTRA_DEPENDENCIES
67
+
68
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
69
+ end
70
+
71
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
72
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
73
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
74
+ $hoe.rsync_args = '-av --delete --ignore-errors'
75
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,49 @@
1
+ # Ported from John Nunemaker's Scrobbler Gem (http://scrobbler.rubyforge.org/)
2
+
3
+ require 'net/https'
4
+
5
+ module REST
6
+ class Connection
7
+ def initialize(base_url, args = {})
8
+ @base_url = base_url
9
+ @username = args['username']
10
+ @password = args['password']
11
+ @app_id = args['app_id']
12
+ end
13
+
14
+ def get(resource, args = nil)
15
+ request(resource, "get", args)
16
+ end
17
+
18
+ def post(resource, args = nil)
19
+ request(resource, "post", args)
20
+ end
21
+
22
+ def request(resource, method = "get", args = {})
23
+ url = URI.join(@base_url, resource)
24
+
25
+ if args = args.update('appid' => @app_id)
26
+ # TODO: What about keys without value?
27
+ url.query = args.map { |k,v| "%s=%s" % [URI.encode(k.to_s), URI.encode(v.to_s)] }.join("&")
28
+ end
29
+
30
+ case method
31
+ when "get"
32
+ req = Net::HTTP::Get.new(url.request_uri)
33
+ when "post"
34
+ req = Net::HTTP::Post.new(url.request_uri)
35
+ end
36
+
37
+ if @username and @password
38
+ req.basic_auth(@username, @password)
39
+ end
40
+
41
+ http = Net::HTTP.new(url.host, url.port)
42
+ http.use_ssl = (url.port == 443)
43
+
44
+ res = http.start() { |conn| conn.request(req) }
45
+ puts url
46
+ res.body
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ %w{rubygems cgi hpricot activesupport}.each { |x| require x }
2
+
3
+ $:.unshift(File.dirname(__FILE__)) unless
4
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require 'rest'
7
+ require 'yahoo-geoplanet/base'
8
+ require 'yahoo-geoplanet/version'
9
+
10
+ require 'yahoo-geoplanet/place'
11
+
12
+ module Yahoo
13
+ module GeoPlanet
14
+ LOCALE = "us"
15
+ API_VERSION = "v1"
16
+ API_URL = "http://where.yahooapis.com/v1/"
17
+
18
+ class << self
19
+ def app_id=(_id)
20
+ Yahoo::GeoPlanet::Base::connection = REST::Connection.new(API_URL, 'app_id' => _id)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,48 @@
1
+ module Yahoo
2
+ module GeoPlanet
3
+ class Base
4
+ class << self
5
+ cattr_accessor :connection
6
+
7
+ def name_with_demodulization
8
+ self.name_without_demodulization.demodulize
9
+ end
10
+
11
+ alias_method_chain :name, :demodulization
12
+
13
+ def fetch_and_parse(resource, options = {})
14
+ raise YahooWebServiceError, "No App ID specified" if connection.nil?
15
+ return Hpricot::XML(connection.get(resource, options))
16
+ end
17
+
18
+ def api_path(resource, id, collection, *args)
19
+ parameters = [resource, id, collection, *args].compact
20
+ return parameters.collect!{|param| CGI::escape(param.to_s).downcase}.join('/')
21
+ end
22
+ end
23
+
24
+ def initialize(xml)
25
+ raise ArgumentError unless xml.kind_of?(Hpricot)
26
+ end
27
+
28
+ def initialize_with_polymorphism(arg)
29
+ case arg
30
+ when Integer
31
+ initialize_without_polymorphism(query_by_id(arg))
32
+ when Hpricot
33
+ initialize_without_polymorphism(arg)
34
+ end
35
+ end
36
+
37
+ alias_method_chain :initialize, :polymorphism
38
+
39
+ protected
40
+ def query_by_id(id)
41
+ xml = self.class.fetch_and_parse(self.class.api_path(self.class.name, id, nil))
42
+ return xml.at(self.class.name.downcase)
43
+ end
44
+ end
45
+
46
+ class YahooWebServiceError < StandardError; end
47
+ end
48
+ end
@@ -0,0 +1,73 @@
1
+ module Yahoo
2
+ module GeoPlanet
3
+ class Place < Base
4
+ attr_reader :woe_id, :type, :name
5
+ attr_reader :latitude, :longitude, :bounding_box
6
+ alias_method :lat, :latitude
7
+ alias_method :lon, :longitude
8
+
9
+ def initialize_without_polymorphism(xml)
10
+ super
11
+
12
+ @woe_id = xml.at("woeid").inner_text
13
+ @type = xml.at("placeTypeName").inner_text
14
+ @name = xml.at("name").inner_text
15
+
16
+ ["admin1", "admin2", "admin3", "locality1", "locality2", "postal"].each do |optional|
17
+ begin
18
+ element = xml.at(optional)
19
+ type = element.attributes["type"].downcase.gsub(/\s+/, '_')
20
+ value = element.inner_text
21
+
22
+ self.class.class_eval %(attr_accessor :#{type})
23
+ self.instance_variable_set("@#{type}", value)
24
+ rescue
25
+ next
26
+ end
27
+ end
28
+
29
+ element = xml.at("centroid")
30
+ @latitude = element.at("latitude").inner_text.to_f
31
+ @longitude = element.at("longitude").inner_text.to_f
32
+
33
+ element = xml.at("boundingBox")
34
+ @bounding_box = ["northEast","southWest"].collect do |corner|
35
+ corner = element.at(corner)
36
+ [corner.at("latitude"), corner.at("longitude")].collect{|e| e.inner_text.to_f}
37
+ end
38
+ end
39
+
40
+ # Association Collections
41
+ ["parent", "ancestors", "belongtos", "neighbors", "siblings", "children"].each do |association|
42
+ define_method(association.to_sym) do
43
+ xml = self.class.fetch_and_parse(self.class.api_path(self.class.name, @woe_id, association), :select => :long)
44
+ value = xml.search(self.class.name.downcase).collect{|elem| self.class.new(elem)}
45
+ return association.singularize == association ? value.first : value
46
+ end
47
+ end
48
+
49
+ def to_s
50
+ self.name
51
+ end
52
+
53
+ def to_i
54
+ self.woe_id.to_i
55
+ end
56
+
57
+ class << self
58
+ def search(query, options = {'count' => '20'})
59
+ query = URI.encode(query.gsub(/\s+/, '+'))
60
+ if options[:type]
61
+ type = options.delete(:type).gsub(/\s+/, '+')
62
+ term = "$and(.q('#{query}'),.type('#{type}'));"
63
+ else
64
+ term = ".q('#{query}');"
65
+ end
66
+ term << options.collect{|k,v| "%s=%s" % [URI.encode(k.to_s), URI.encode(v.to_s)]}.join(";")
67
+ xml = fetch_and_parse('places' + term)
68
+ return xml.search(self.name.downcase).collect{|elem| self.new(elem)}
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ module Yahoo
2
+ module GeoPlanet
3
+ module VERSION #:nodoc:
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ TINY = 0
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+ end
11
+ end