ym4r 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +7 -0
- data/README +60 -0
- data/lib/ym4r.rb +4 -0
- data/lib/ym4r/app_id.rb +3 -0
- data/lib/ym4r/building_block/geocoding.rb +81 -0
- data/lib/ym4r/building_block/local_search.rb +156 -0
- data/lib/ym4r/building_block/map_image.rb +76 -0
- data/lib/ym4r/building_block/traffic.rb +120 -0
- data/lib/ym4r/exception.rb +18 -0
- data/rakefile.rb +49 -0
- data/test/test_geocoding.rb +37 -0
- data/test/test_local_search.rb +62 -0
- data/test/test_map_image.rb +37 -0
- data/test/test_traffic.rb +33 -0
- metadata +62 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+ym4r@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
=YM4R
|
2
|
+
The goal of YM4R is to ease the use of all the Yahoo! Maps API's (including the Geocoding, Map Image, Traffic and Local Search API's) from Ruby and Rails.
|
3
|
+
|
4
|
+
===Operations
|
5
|
+
At this time, only the Building Block API's (Geocoding, Map Image, Traffic and Local Search) are supported. You have to pass to the +get+ method of the module a hash whose keys are a rubyfied version of the request parameters. You get back a ruby object, with accessors that let you get the returned data in a easy way. You get an exception if not all the parameters have been passed, if the connection to the service could not be made or if the parameters you have passed are of the incorrect value.
|
6
|
+
|
7
|
+
To know what parameters to pass to the +get+ methods and what results you should expect, you should consult the documentation for the building block API's on YahoooOooOoooOoo!'s website : http://developer.yahoo.com/maps/index.html#mapsBuildingBlocks .
|
8
|
+
|
9
|
+
Here are some examples and notes about using the different Building Block API's.
|
10
|
+
====Geocoding
|
11
|
+
Here is an example of request:
|
12
|
+
require 'ym4r'
|
13
|
+
include Ym4r::BuildingBlock
|
14
|
+
results = Geocoding::get(:street => "1 Infinite Loop",
|
15
|
+
:city => "Cupertino",
|
16
|
+
:state => "CA",
|
17
|
+
:zip => "95014")
|
18
|
+
+results+ is an array of Geocoding::Result objects. The API can return up to 50 results for one request. Read the documentation page of the Geocoding::Result class to know how to access the data.
|
19
|
+
|
20
|
+
====Map Image
|
21
|
+
Here is an example of request:
|
22
|
+
require 'ym4r'
|
23
|
+
include Ym4r::BuildingBlock
|
24
|
+
result = MapImage::get(:street => "1 Infinite Loop",
|
25
|
+
:city => "Cupertino",
|
26
|
+
:state => "CA",
|
27
|
+
:zip => "95014",
|
28
|
+
:image_type => "png")
|
29
|
+
+result+ is a MapImage::Result object contains the URL for the requested image. You can download this image to a file by calling +download_to+ and passing a path.
|
30
|
+
|
31
|
+
====Traffic
|
32
|
+
Here is an example of request:
|
33
|
+
require 'ym4r'
|
34
|
+
include Ym4r::BuildingBlock
|
35
|
+
results = Traffic::get(:street => "1 Infinite Loop",
|
36
|
+
:city => "Cupertino",
|
37
|
+
:state => "CA",
|
38
|
+
:zip => "95014",
|
39
|
+
:include_map => true)
|
40
|
+
+results+ is a Traffic::ResultSet object (subclass of +Array+), containing Traffic::Result objects, each containing information about one traffic incident.
|
41
|
+
|
42
|
+
====Local Search
|
43
|
+
Here is an example of request:
|
44
|
+
require 'ym4r'
|
45
|
+
include Ym4r::BuildingBlock
|
46
|
+
results = LocalSearch::get(:street => "1 Infinite Loop",
|
47
|
+
:city => "Cupertino",
|
48
|
+
:state => "CA",
|
49
|
+
:zip => "95014",
|
50
|
+
:query => "chinese")
|
51
|
+
+results+ is a LocalSearch::ResultSet object (subclass of +Array+), containing LocalSearch::Result objects, each containing information about one hit on the Yahoo! local search.
|
52
|
+
|
53
|
+
===Disclaimer
|
54
|
+
This software is not endorsed in any way by Yahoo!.
|
55
|
+
|
56
|
+
===License
|
57
|
+
YM4R is released under the MIT license.
|
58
|
+
|
59
|
+
===Support
|
60
|
+
Any questions, enhancement proposals, bug notifications or corrections can be sent to mailto:guilhem.vellut+ym4r@gmail.com.
|
data/lib/ym4r.rb
ADDED
data/lib/ym4r/app_id.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'ym4r/app_id'
|
2
|
+
require 'ym4r/exception'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module Ym4r
|
7
|
+
module BuildingBlock
|
8
|
+
module Geocoding
|
9
|
+
#Sends a request to the Yahoo! Maps geocoding service and returns the result in an easy to use Ruby object, hiding the creation of the query string and the XML parsing of the answer.
|
10
|
+
def self.get(param)
|
11
|
+
unless param.has_key?(:street) or
|
12
|
+
param.has_key?(:city) or
|
13
|
+
param.has_key?(:state) or
|
14
|
+
param.has_key?(:zip) or
|
15
|
+
param.has_key?(:location)
|
16
|
+
raise Ym4r::MissingParameterException.new("Missing location data for the Yahoo! Maps Geocoding service")
|
17
|
+
end
|
18
|
+
|
19
|
+
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{Ym4r::APP_ID}&"
|
20
|
+
url << "street=#{param[:street]}&" if param.has_key?(:street)
|
21
|
+
url << "city=#{param[:city]}&" if param.has_key?(:city)
|
22
|
+
url << "state=#{param[:state]}&" if param.has_key?(:state)
|
23
|
+
url << "zip=#{param[:zip]}&" if param.has_key?(:zip)
|
24
|
+
url << "location=#{param[:location]}&" if param.has_key?(:location)
|
25
|
+
url << "output=xml"
|
26
|
+
|
27
|
+
begin
|
28
|
+
xml = open(URI.encode(url)).read
|
29
|
+
rescue OpenURI::HTTPError => error
|
30
|
+
raise Ym4r::BadRequestException.new(error.to_s)
|
31
|
+
rescue
|
32
|
+
raise Ym4r::ConnectionException.new("Unable to connect to Yahoo! Maps Geocoding service")
|
33
|
+
end
|
34
|
+
|
35
|
+
doc = REXML::Document.new(xml)
|
36
|
+
|
37
|
+
if doc.root.name == "Error"
|
38
|
+
raise Ym4r::RateLimitExceededException.new("Rate limit exceeded for Yahoo! Maps Geocoding service")
|
39
|
+
else
|
40
|
+
results = []
|
41
|
+
doc.elements.each("//Result") do |result|
|
42
|
+
data = result.elements
|
43
|
+
results << Geocoding::Result.new(result.attributes['precision'],
|
44
|
+
result.attributes['warning'],
|
45
|
+
data['Latitude'].text.to_f,
|
46
|
+
data['Longitude'].text.to_f,
|
47
|
+
data['Address'].text,
|
48
|
+
data['City'].text,
|
49
|
+
data['State'].text,
|
50
|
+
data['Zip'].text,
|
51
|
+
data['Country'].text)
|
52
|
+
end
|
53
|
+
results
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#Contains a result match from the Yahoo! Maps geocoding service.
|
58
|
+
class Result < Struct.new(:precision,:warning,:latitude,:longitude,:address,:city,:state,:zip,:country)
|
59
|
+
|
60
|
+
#Convenience method for the lazy.
|
61
|
+
def latlon
|
62
|
+
[latitude,longitude]
|
63
|
+
end
|
64
|
+
|
65
|
+
#Convenience method for the lazy.
|
66
|
+
def lonlat
|
67
|
+
[longitude,latitude]
|
68
|
+
end
|
69
|
+
|
70
|
+
#Indicates if the location passed in the request could be exactly identified.
|
71
|
+
def exact_match?
|
72
|
+
warning.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end #Geocoding
|
78
|
+
|
79
|
+
end #BuildingBlock
|
80
|
+
|
81
|
+
end #Ym4r
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'ym4r/app_id'
|
2
|
+
require 'ym4r/exception'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module Ym4r
|
7
|
+
module BuildingBlock
|
8
|
+
module LocalSearch
|
9
|
+
#Send a request to the local search REST API V3.
|
10
|
+
def self.get(param)
|
11
|
+
|
12
|
+
unless param.has_key?(:street) or
|
13
|
+
param.has_key?(:city) or
|
14
|
+
param.has_key?(:state) or
|
15
|
+
param.has_key?(:zip) or
|
16
|
+
param.has_key?(:location) or
|
17
|
+
(param.has_key?(:longitude) and param.has_key?(:latitude))
|
18
|
+
raise Ym4r::MissingParameterException.new("Missing location data for the Yahoo! Maps Local Search service")
|
19
|
+
end
|
20
|
+
|
21
|
+
unless param.has_key?(:query) or
|
22
|
+
param.has_key?(:listing_id)
|
23
|
+
raise Ym4r::MissingParameterException.new("Missing query data for the Yahoo! Maps Local Search service")
|
24
|
+
end
|
25
|
+
|
26
|
+
url = "http://api.local.yahoo.com/LocalSearchService/V3/localSearch?appid=#{Ym4r::APP_ID}&"
|
27
|
+
url << "query=#{param[:query]}&" if param.has_key?(:query)
|
28
|
+
url << "listing_id=#{param[:query]}&" if param.has_key?(:listing_id)
|
29
|
+
url << "results=#{param[:results]}&" if param.has_key?(:results)
|
30
|
+
url << "start=#{param[:start]}&" if param.has_key?(:start)
|
31
|
+
url << "sort=#{param[:sort]}&" if param.has_key?(:sort)
|
32
|
+
url << "radius=#{param[:radius]}&" if param.has_key?(:radius)
|
33
|
+
url << "street=#{param[:street]}&" if param.has_key?(:street)
|
34
|
+
url << "city=#{param[:city]}&" if param.has_key?(:city)
|
35
|
+
url << "state=#{param[:state]}&" if param.has_key?(:state)
|
36
|
+
url << "zip=#{param[:zip]}&" if param.has_key?(:zip)
|
37
|
+
url << "location=#{param[:location]}&" if param.has_key?(:location)
|
38
|
+
url << "latitude=#{param[:latitude]}&" if param.has_key?(:latitude)
|
39
|
+
url << "longitude=#{param[:longitude]}&" if param.has_key?(:longitude)
|
40
|
+
url << "category=#{param[:category]}&" if param.has_key?(:category)
|
41
|
+
url << "omit_category=#{param[:omit_category]}&" if param.has_key?(:omit_category)
|
42
|
+
url << "minimum_rating=#{param[:minimum_rating]}&" if param.has_key?(:minimum_rating)
|
43
|
+
url << "output=json"
|
44
|
+
|
45
|
+
begin
|
46
|
+
json = open(URI.encode(url)).read
|
47
|
+
rescue OpenURI::HTTPError => error
|
48
|
+
raise Ym4r::BadRequestException.new(error.to_s)
|
49
|
+
rescue
|
50
|
+
raise Ym4r::ConnectionException.new("Unable to connect to Yahoo! Maps REST service")
|
51
|
+
end
|
52
|
+
|
53
|
+
#see http://rubyforge.org/snippet/detail.php?type=snippet&id=29. Safe?
|
54
|
+
json_obj = eval(json.gsub(/(["'])\s*:\s*(['"0-9tfn\[{])/){"#{$1}=>#{$2}"})
|
55
|
+
|
56
|
+
if json_obj.has_key?("Error")
|
57
|
+
raise Ym4r::RateLimitExceededException.new("Rate limit exceeded for Yahoo! Maps Traffic REST service")
|
58
|
+
else
|
59
|
+
json_result_set = json_obj['ResultSet']
|
60
|
+
|
61
|
+
result_set = LocalSearch::ResultSet.new(json_result_set['ResultSetMapUrl'],
|
62
|
+
json_result_set['totalResultsAvailable'].to_i,
|
63
|
+
json_result_set['totalResultsReturned'].to_i,
|
64
|
+
json_result_set['firstResultPosition'].to_i)
|
65
|
+
|
66
|
+
unless json_result_set['Result'].nil?
|
67
|
+
json_results = [json_result_set['Result']].flatten #uniform processing in case there is only one result
|
68
|
+
|
69
|
+
json_results.each do |json_result|
|
70
|
+
|
71
|
+
#get the rating
|
72
|
+
json_rating = json_result['Rating']
|
73
|
+
rating = LocalSearch::Rating.new(json_rating['AverageRating'].to_f, #when NaN, converted to 0 but can be tested (since TotalRating is 0 in this case) with is_rated? on the rating object
|
74
|
+
json_rating['TotalRatings'].to_i,
|
75
|
+
json_rating['TotalReviews'].to_i,
|
76
|
+
Time.at(json_rating['LastReviewDate'].to_i),
|
77
|
+
json_rating['LastReviewIntro'])
|
78
|
+
|
79
|
+
#get the categories
|
80
|
+
categories = []
|
81
|
+
unless json_result['Categories']['Category'].nil? #no category present in the result
|
82
|
+
json_categories = [json_result['Categories']['Category']].flatten #uniform processing in case there is only one category
|
83
|
+
json_categories.each do |json_category|
|
84
|
+
categories << LocalSearch::Category.new(json_category['id'].to_i,
|
85
|
+
json_category['content'])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
result_set << LocalSearch::Result.new(json_result['id'].to_i,
|
90
|
+
json_result['Title'],
|
91
|
+
json_result['Address'],
|
92
|
+
json_result['City'],
|
93
|
+
json_result['State'],
|
94
|
+
json_result['Phone'],
|
95
|
+
json_result['Latitude'].to_f,
|
96
|
+
json_result['Longitude'].to_f,
|
97
|
+
rating,
|
98
|
+
json_result['Distance'].to_f,
|
99
|
+
json_result['Url'],
|
100
|
+
json_result['ClickUrl'],
|
101
|
+
json_result['MapUrl'],
|
102
|
+
json_result['BusinessUrl'],
|
103
|
+
json_result['BusinessClickUrl'],
|
104
|
+
categories)
|
105
|
+
|
106
|
+
end
|
107
|
+
end #unless json_result_set['Result'].nil?
|
108
|
+
|
109
|
+
result_set
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#Contains a list of results from the Yahoo! Maps Local Search REST service V3
|
115
|
+
class ResultSet < Array
|
116
|
+
attr_accessor :map_url, :total_results_available, :total_results_returned, :first_result_position
|
117
|
+
|
118
|
+
def initialize(map_url,total_results_available, total_results_returned, first_result_position)
|
119
|
+
super(0)
|
120
|
+
@map_url = map_url
|
121
|
+
@total_results_available = total_results_available
|
122
|
+
@total_results_returned = total_results_returned
|
123
|
+
@first_result_position = first_result_position
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
#Contains a result from the Yahoo! Maps Local Search REST service V3.
|
129
|
+
class Result < Struct.new(:id,:title,:address,:city,:state,:phone,:latitude,:longitude,:rating,:distance,:url,:click_url,:map_url,:business_url,:business_click_url,:categories)
|
130
|
+
|
131
|
+
#convenience method for the lazy
|
132
|
+
def lonlat
|
133
|
+
[longitude,latitude]
|
134
|
+
end
|
135
|
+
|
136
|
+
#convenience method for the lazy
|
137
|
+
def latlon
|
138
|
+
[latitude,longitude]
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
class Category < Struct.new(:id,:name)
|
144
|
+
end
|
145
|
+
|
146
|
+
class Rating < Struct.new(:average_rating,:total_ratings,:total_reviews,:last_review_date,:last_review_intro)
|
147
|
+
def is_rated?
|
148
|
+
total_ratings != 0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end #LocalSearch
|
153
|
+
|
154
|
+
end #BuildingBlock
|
155
|
+
|
156
|
+
end #Ym4r
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'ym4r/app_id'
|
2
|
+
require 'ym4r/exception'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module Ym4r
|
7
|
+
module BuildingBlock
|
8
|
+
module MapImage
|
9
|
+
#Send a request to the Map image API. Gets back a url to an image. This image can be downloaded later.
|
10
|
+
def self.get(param)
|
11
|
+
unless param.has_key?(:street) or
|
12
|
+
param.has_key?(:city) or
|
13
|
+
param.has_key?(:state) or
|
14
|
+
param.has_key?(:zip) or
|
15
|
+
param.has_key?(:location) or
|
16
|
+
(param.has_key?(:longitude) and param.has_key?(:latitude))
|
17
|
+
raise Ym4r::MissingParameterException.new("Missing location data for the Yahoo! Maps Map Image service")
|
18
|
+
end
|
19
|
+
|
20
|
+
url = "http://api.local.yahoo.com/MapsService/V1/mapImage?appid=#{Ym4r::APP_ID}&"
|
21
|
+
url << "street=#{param[:street]}&" if param.has_key?(:street)
|
22
|
+
url << "city=#{param[:city]}&" if param.has_key?(:city)
|
23
|
+
url << "state=#{param[:state]}&" if param.has_key?(:state)
|
24
|
+
url << "zip=#{param[:zip]}&" if param.has_key?(:zip)
|
25
|
+
url << "location=#{param[:location]}&" if param.has_key?(:location)
|
26
|
+
url << "latitude=#{param[:latitude]}&" if param.has_key?(:latitude)
|
27
|
+
url << "longitude=#{param[:longitude]}&" if param.has_key?(:longitude)
|
28
|
+
url << "image_type=#{param[:image_type]}&" if param.has_key?(:image_type) #defaults to PNG
|
29
|
+
url << "image_height=#{param[:image_height]}&" if param.has_key?(:image_height) #defaults to 500
|
30
|
+
url << "image_width=#{param[:image_width]}&" if param.has_key?(:image_width) #defaults to 620
|
31
|
+
url << "zoom=#{param[:zoom]}&" if param.has_key?(:zoom) #defaults to 6
|
32
|
+
url << "radius=#{param[:radius]}&" if param.has_key?(:radius)
|
33
|
+
url << "output=xml"
|
34
|
+
|
35
|
+
begin
|
36
|
+
xml = open(URI.encode(url)).read
|
37
|
+
rescue OpenURI::HTTPError => error
|
38
|
+
raise Ym4r::BadRequestException.new(error.to_s)
|
39
|
+
rescue
|
40
|
+
raise Ym4r::ConnectionException.new("Unable to connect to Yahoo! Maps Map Image service")
|
41
|
+
end
|
42
|
+
|
43
|
+
doc = REXML::Document.new(xml)
|
44
|
+
|
45
|
+
if doc.root.name == "Error"
|
46
|
+
raise Ym4r::RateLimitExceededException.new("Rate limit exceeded for Yahoo! Maps Map Image service")
|
47
|
+
else
|
48
|
+
result = doc.root
|
49
|
+
MapImage::Result.new(result.attributes['warning'],
|
50
|
+
result.text)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#Contains a result match from the Yahoo! Maps Map Image service.
|
55
|
+
class Result < Struct.new(:warning,:url)
|
56
|
+
|
57
|
+
#Downloads the image to +file+.
|
58
|
+
def download_to(file)
|
59
|
+
data = open(url).read
|
60
|
+
open(file,"wb") do |f|
|
61
|
+
f.write data
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#Indicates if the location passed in the request could be exactly identified.
|
66
|
+
def exact_match?
|
67
|
+
warning.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end #MapImage
|
73
|
+
|
74
|
+
end #BuildingBlock
|
75
|
+
|
76
|
+
end #Ym4r
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'ym4r/app_id'
|
2
|
+
require 'ym4r/exception'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'rexml/document'
|
5
|
+
|
6
|
+
module Ym4r
|
7
|
+
module BuildingBlock
|
8
|
+
module Traffic
|
9
|
+
#Send a request to the traffic REST API.
|
10
|
+
def self.get(param)
|
11
|
+
unless param.has_key?(:street) or
|
12
|
+
param.has_key?(:city) or
|
13
|
+
param.has_key?(:state) or
|
14
|
+
param.has_key?(:zip) or
|
15
|
+
param.has_key?(:location) or
|
16
|
+
(param.has_key?(:longitude) and param.has_key?(:latitude))
|
17
|
+
raise Ym4r::MissingParameterException.new("Missing location data for the Yahoo! Maps Traffic service")
|
18
|
+
end
|
19
|
+
|
20
|
+
url = "http://api.local.yahoo.com/MapsService/V1/trafficData?appid=#{Ym4r::APP_ID}&"
|
21
|
+
url << "street=#{param[:street]}&" if param.has_key?(:street)
|
22
|
+
url << "city=#{param[:city]}&" if param.has_key?(:city)
|
23
|
+
url << "state=#{param[:state]}&" if param.has_key?(:state)
|
24
|
+
url << "zip=#{param[:zip]}&" if param.has_key?(:zip)
|
25
|
+
url << "location=#{param[:location]}&" if param.has_key?(:location)
|
26
|
+
url << "latitude=#{param[:latitude]}&" if param.has_key?(:latitude)
|
27
|
+
url << "longitude=#{param[:longitude]}&" if param.has_key?(:longitude)
|
28
|
+
url << "image_type=#{param[:image_type]}&" if param.has_key?(:image_type) #defaults to PNG
|
29
|
+
url << "image_height=#{param[:image_height]}&" if param.has_key?(:image_height) #defaults to 500
|
30
|
+
url << "image_width=#{param[:image_width]}&" if param.has_key?(:image_width) #defaults to 620
|
31
|
+
url << "zoom=#{param[:zoom]}&" if param.has_key?(:zoom) #defaults to 6
|
32
|
+
url << "radius=#{param[:radius]}&" if param.has_key?(:radius)
|
33
|
+
url << "include_map=#{param[:include_map]?1:0}&" if param.has_key?(:include_map)
|
34
|
+
url << "severity=#{param[:severity]}&" if param.has_key?(:severity)
|
35
|
+
url << "output=xml"
|
36
|
+
|
37
|
+
begin
|
38
|
+
xml = open(URI.encode(url)).read
|
39
|
+
rescue OpenURI::HTTPError => error
|
40
|
+
raise Ym4r::BadRequestException.new(error.to_s)
|
41
|
+
rescue
|
42
|
+
raise Ym4r::ConnectionException.new("Unable to connect to Yahoo! Maps Traffic REST service")
|
43
|
+
end
|
44
|
+
|
45
|
+
doc = REXML::Document.new(xml)
|
46
|
+
|
47
|
+
if doc.root.name == "Error"
|
48
|
+
raise Ym4r::RateLimitExceededException.new("Rate limit exceeded for Yahoo! Maps Traffic REST service")
|
49
|
+
else
|
50
|
+
results = Traffic::ResultSet.new(Time.at(doc.root.elements['LastUpdateDate'].text.to_i),doc.root.elements['Warning'].nil? ? nil : doc.root.elements['Warning'].text)
|
51
|
+
|
52
|
+
doc.root.elements.each('//Result') do |result|
|
53
|
+
data = result.elements
|
54
|
+
results << Traffic::Result.new(result.attributes['type'],
|
55
|
+
data['Title'].text,
|
56
|
+
data['Description'].text,
|
57
|
+
data['Latitude'].text.to_f,
|
58
|
+
data['Longitude'].text.to_f,
|
59
|
+
data['Direction'].text,
|
60
|
+
data['Severity'].text.to_i,
|
61
|
+
Time.at(data['ReportDate'].text.to_i),
|
62
|
+
Time.at(data['UpdateDate'].text.to_i),
|
63
|
+
Time.at(data['EndDate'].text.to_i),
|
64
|
+
data['ImageUrl'].nil? ? nil : data['ImageUrl'].text)
|
65
|
+
end
|
66
|
+
results
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#Contains a list of results from the Yahoo! Maps Traffic REST API
|
72
|
+
class ResultSet < Array
|
73
|
+
attr_accessor :last_update_date,:warning
|
74
|
+
|
75
|
+
def initialize(last_update_date,warning)
|
76
|
+
super(0)
|
77
|
+
@last_update_date = last_update_date
|
78
|
+
@warning = warning
|
79
|
+
end
|
80
|
+
|
81
|
+
#Indicates if the location passed in the request could be exactly identified.
|
82
|
+
def exact_match?
|
83
|
+
warning.nil?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#Contains a result from the Yahoo! Maps Traffic REST service.
|
88
|
+
class Result < Struct.new(:type,:title,:description,:latitude,:longitude,:direction,:severity,:report_date,:update_date,:end_date,:image_url)
|
89
|
+
|
90
|
+
#Downloads the image (if there is one) to +file+.
|
91
|
+
def download_to(file)
|
92
|
+
if has_image?
|
93
|
+
data = open(image_url).read
|
94
|
+
open(file,"wb") do |f|
|
95
|
+
f.write data
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def has_image?
|
101
|
+
! image_url.nil?
|
102
|
+
end
|
103
|
+
|
104
|
+
#Convenience method for the lazy.
|
105
|
+
def lonlat
|
106
|
+
[longitude,latitude]
|
107
|
+
end
|
108
|
+
|
109
|
+
#Convenience method for the lazy.
|
110
|
+
def latlon
|
111
|
+
[latitude,longitude]
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end #Traffic
|
117
|
+
|
118
|
+
end #BuildingBlock
|
119
|
+
|
120
|
+
end #Ym4r
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ym4r
|
2
|
+
#Raised if the rate limit per 24 hours per IP is reached
|
3
|
+
class RateLimitExceededException < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
#Raised if the Yahoo Maps building bloc service is unreachable
|
7
|
+
class ConnectionException < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
#Raised if the service returns an HTTP error (due to bad arguments passed to the service)
|
11
|
+
class BadRequestException < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
#Raised if all the data needed is not passed to the get method of the service
|
15
|
+
class MissingParameterException < StandardError
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/rakefile.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc "Run the tests"
|
9
|
+
Rake::TestTask::new do |t|
|
10
|
+
t.test_files = FileList['test/test*.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Generate the documentation"
|
15
|
+
Rake::RDocTask::new do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'ym4r-doc/'
|
17
|
+
rdoc.title = "Yahoo Maps for Ruby Documentation"
|
18
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
19
|
+
rdoc.rdoc_files.include('README')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
spec = Gem::Specification::new do |s|
|
24
|
+
s.platform = Gem::Platform::RUBY
|
25
|
+
|
26
|
+
s.name = 'ym4r'
|
27
|
+
s.version = "0.0.1"
|
28
|
+
s.summary = "Using the Yahoo Maps API from Ruby"
|
29
|
+
s.description = <<EOF
|
30
|
+
EOF
|
31
|
+
s.author = 'Guilhem Vellut'
|
32
|
+
s.email = 'guilhem.vellut+ym4r@gmail.com'
|
33
|
+
s.homepage = "http://thepochisuperstarmegashow.com"
|
34
|
+
|
35
|
+
s.requirements << 'none'
|
36
|
+
s.require_path = 'lib'
|
37
|
+
s.files = FileList["lib/**/*.rb", "test/**/*.rb", "README","MIT-LICENSE","rakefile.rb"]
|
38
|
+
s.test_files = FileList['test/test*.rb']
|
39
|
+
|
40
|
+
s.has_rdoc = true
|
41
|
+
s.extra_rdoc_files = ["README"]
|
42
|
+
s.rdoc_options.concat ['--main', 'README']
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Package the library as a gem"
|
46
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
47
|
+
pkg.need_zip = true
|
48
|
+
pkg.need_tar = true
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ym4r'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include Ym4r::BuildingBlock
|
7
|
+
|
8
|
+
class TestGeocoding< Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_apple
|
11
|
+
results1 = Geocoding::get(:street => "1 Infinite Loop",
|
12
|
+
:city => "Cupertino",
|
13
|
+
:state => "CA",
|
14
|
+
:zip => "95014")
|
15
|
+
assert_equal(1,results1.length)
|
16
|
+
result1 = results1[0]
|
17
|
+
assert(result1.exact_match?)
|
18
|
+
assert_equal("address",result1.precision)
|
19
|
+
|
20
|
+
results2 = Geocoding::get(:location => "1 Infinite Loop Cupertino CA 95014")
|
21
|
+
assert_equal(1,results2.length)
|
22
|
+
result2 = results2[0]
|
23
|
+
assert(result2.exact_match?)
|
24
|
+
|
25
|
+
assert_equal(result1.latitude,result2.latitude)
|
26
|
+
assert_equal(result1.longitude,result2.longitude)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_garbage_location
|
30
|
+
assert_raise(Ym4r::BadRequestException) {Geocoding::get(:location => "AZEAEAEAEAEAE")}
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_no_location
|
34
|
+
assert_raise(Ym4r::MissingParameterException) {Geocoding::get(:hello => "world")}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ym4r'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include Ym4r::BuildingBlock
|
7
|
+
|
8
|
+
class TestLocalSearch< Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_apple
|
11
|
+
results = LocalSearch::get(:street => "1 Infinite Loop",
|
12
|
+
:city => "Cupertino",
|
13
|
+
:state => "CA",
|
14
|
+
:zip => "95014",
|
15
|
+
:query => "chinese")
|
16
|
+
|
17
|
+
assert(! results.nil?)
|
18
|
+
|
19
|
+
results.each do |result|
|
20
|
+
assert(!result.id.nil?)
|
21
|
+
assert(!result.title.nil?)
|
22
|
+
assert(!result.address.nil?)
|
23
|
+
assert(!result.city.nil?)
|
24
|
+
assert(!result.state.nil?)
|
25
|
+
assert(!result.phone.nil?)
|
26
|
+
assert(!result.latitude.nil?)
|
27
|
+
assert(!result.longitude.nil?)
|
28
|
+
assert(!result.rating.nil?)
|
29
|
+
assert(result.rating.is_a?(LocalSearch::Rating))
|
30
|
+
assert(!result.url.nil?)
|
31
|
+
assert(!result.click_url.nil?)
|
32
|
+
assert(!result.map_url.nil?)
|
33
|
+
assert(!result.business_url.nil?)
|
34
|
+
assert(!result.business_click_url.nil?)
|
35
|
+
assert(!result.categories.nil?)
|
36
|
+
assert(result.categories.is_a?(Array))
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_no_query
|
43
|
+
assert_raise(Ym4r::MissingParameterException) do
|
44
|
+
LocalSearch::get(:street => "1 Infinite Loop",
|
45
|
+
:city => "Cupertino",
|
46
|
+
:state => "CA",
|
47
|
+
:zip => "95014")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_random_query
|
52
|
+
results = LocalSearch::get(:street => "1 Infinite Loop",
|
53
|
+
:city => "Cupertino",
|
54
|
+
:state => "CA",
|
55
|
+
:zip => "95014",
|
56
|
+
:query => "AZEAEAEZAEAEAE")
|
57
|
+
assert(!results.nil?)
|
58
|
+
|
59
|
+
assert_equal(0,results.length)
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ym4r'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include Ym4r::BuildingBlock
|
7
|
+
|
8
|
+
class TestMapImage< Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_apple
|
11
|
+
result = MapImage::get(:street => "1 Infinite Loop",
|
12
|
+
:city => "Cupertino",
|
13
|
+
:state => "CA",
|
14
|
+
:zip => "95014",
|
15
|
+
:image_type => "png")
|
16
|
+
assert(result.exact_match?)
|
17
|
+
apple_image = "apple.png"
|
18
|
+
result.download_to(apple_image)
|
19
|
+
assert(File.exist?(apple_image))
|
20
|
+
File.delete(apple_image)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_no_location
|
24
|
+
assert_raise(Ym4r::MissingParameterException) {MapImage::get(:image_type => "gif")}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_bad_parameter
|
28
|
+
assert_raise(Ym4r::BadRequestException) do
|
29
|
+
MapImage::get(:street => "1 Infinite Loop",
|
30
|
+
:city => "Cupertino",
|
31
|
+
:state => "CA",
|
32
|
+
:zip => "95014",
|
33
|
+
:image_type => "jpg") #jpg is not a valid image type
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ym4r'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
include Ym4r::BuildingBlock
|
7
|
+
|
8
|
+
class TestTraffic< Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_apple
|
11
|
+
results = Traffic::get(:street => "1 Infinite Loop",
|
12
|
+
:city => "Cupertino",
|
13
|
+
:state => "CA",
|
14
|
+
:zip => "95014",
|
15
|
+
:include_map => true)
|
16
|
+
|
17
|
+
#since it changes according to time, difficult to test..
|
18
|
+
assert(! results.nil?)
|
19
|
+
assert(results.exact_match?)
|
20
|
+
|
21
|
+
if(!results.empty?)
|
22
|
+
result = results[0]
|
23
|
+
apple_traffic_image = "apple_traffic.png"
|
24
|
+
result.download_to(apple_traffic_image)
|
25
|
+
assert(File.exist?(apple_traffic_image))
|
26
|
+
File.delete(apple_traffic_image)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: ym4r
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2006-05-25 00:00:00 +05:00
|
8
|
+
summary: Using the Yahoo Maps API from Ruby
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: guilhem.vellut+ym4r@gmail.com
|
12
|
+
homepage: http://thepochisuperstarmegashow.com
|
13
|
+
rubyforge_project:
|
14
|
+
description: ""
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Guilhem Vellut
|
30
|
+
files:
|
31
|
+
- lib/ym4r.rb
|
32
|
+
- lib/ym4r/app_id.rb
|
33
|
+
- lib/ym4r/exception.rb
|
34
|
+
- lib/ym4r/building_block/geocoding.rb
|
35
|
+
- lib/ym4r/building_block/local_search.rb
|
36
|
+
- lib/ym4r/building_block/map_image.rb
|
37
|
+
- lib/ym4r/building_block/traffic.rb
|
38
|
+
- test/test_geocoding.rb
|
39
|
+
- test/test_local_search.rb
|
40
|
+
- test/test_map_image.rb
|
41
|
+
- test/test_traffic.rb
|
42
|
+
- README
|
43
|
+
- MIT-LICENSE
|
44
|
+
- rakefile.rb
|
45
|
+
test_files:
|
46
|
+
- test/test_geocoding.rb
|
47
|
+
- test/test_local_search.rb
|
48
|
+
- test/test_map_image.rb
|
49
|
+
- test/test_traffic.rb
|
50
|
+
rdoc_options:
|
51
|
+
- --main
|
52
|
+
- README
|
53
|
+
extra_rdoc_files:
|
54
|
+
- README
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
requirements:
|
60
|
+
- none
|
61
|
+
dependencies: []
|
62
|
+
|