periplus 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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+
9
+ gem "httparty"
10
+
11
+ group :development do
12
+ gem "rspec", "~> 2.4.0"
13
+ gem "bundler", "~> 1.0.0"
14
+ gem "jeweler", "~> 1.6.2"
15
+ gem "rcov", ">= 0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ crack (0.1.8)
5
+ diff-lcs (1.1.2)
6
+ git (1.2.5)
7
+ httparty (0.7.8)
8
+ crack (= 0.1.8)
9
+ jeweler (1.6.2)
10
+ bundler (~> 1.0)
11
+ git (>= 1.2.5)
12
+ rake
13
+ rake (0.9.2)
14
+ rcov (0.9.9)
15
+ rspec (2.4.0)
16
+ rspec-core (~> 2.4.0)
17
+ rspec-expectations (~> 2.4.0)
18
+ rspec-mocks (~> 2.4.0)
19
+ rspec-core (2.4.0)
20
+ rspec-expectations (2.4.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.4.0)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ bundler (~> 1.0.0)
29
+ httparty
30
+ jeweler (~> 1.6.2)
31
+ rcov
32
+ rspec (~> 2.4.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ryan Crum
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.
data/README.rdoc ADDED
@@ -0,0 +1,33 @@
1
+ = periplus
2
+
3
+ Bing Maps REST API client.
4
+
5
+ == Use it
6
+ require 'periplus'
7
+
8
+ my_request = Periplus::Request.new 'my_bing_key'
9
+ response = my_request.route [{:street => "1600 Pennsylvania Ave.",
10
+ :city => "Washington",
11
+ :state => "DC",
12
+ :postal_code => "20500"},
13
+ {:postal_code => "90210"}],
14
+ :distanceUnit => :mi
15
+
16
+ puts "#{response.distance} #{response.distance_units.to_s}.pluralize, #{response.duration} seconds"
17
+ # "2665.06415 miles, 137797 seconds"
18
+
19
+ == Contributing to periplus
20
+
21
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
22
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
23
+ * Fork the project
24
+ * Start a feature/bugfix branch
25
+ * Commit and push until you are happy with your contribution
26
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
27
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
28
+
29
+ == Copyright
30
+
31
+ Copyright (c) 2011 Ryan Crum. See LICENSE.txt for
32
+ further details.
33
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "periplus"
18
+ gem.homepage = "http://github.com/thorstadt/periplus"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Bing Maps REST Client}
21
+ gem.description = %Q{A library that behaves as a client for the Bing Maps REST sdk}
22
+ gem.email = "ryan.j.crum@gmail.com"
23
+ gem.authors = ["Ryan Crum"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "periplus #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/periplus.rb ADDED
@@ -0,0 +1,116 @@
1
+ require "httparty"
2
+
3
+ module Periplus
4
+ class Request
5
+ include HTTParty
6
+ format :json
7
+
8
+ def initialize(api_key)
9
+ @api_key = api_key
10
+ end
11
+
12
+ BING_URL = "http://dev.virtualearth.net/REST/v1/Routes"
13
+ def route(waypoints, options = {})
14
+ options = options.merge(hashify_waypoints(waypoints))
15
+ .merge(:o => "json", :key => @api_key)
16
+ Route.new (self.class.get BING_URL, :query => options)
17
+ end
18
+
19
+ private
20
+ # turns a list of waypoints into a bing-api-friendly "wp.1", "wp.2", etc...
21
+ def hashify_waypoints(waypoints)
22
+ counter = 1
23
+ waypoints.inject({}) do |hash, waypoint|
24
+ hash["wp.#{counter}"] = format_waypoint(waypoint)
25
+ counter = counter + 1
26
+ hash
27
+ end
28
+ end
29
+
30
+ def has_key_or_attribute?(object, key_or_attribute)
31
+ object.respond_to? key_or_attribute or
32
+ (object.respond_to? :has_key? and object.has_key? key_or_attribute)
33
+ end
34
+
35
+ def get_by_key_or_attribute(object, key_or_attribute)
36
+ if object.respond_to? :has_key? and object.has_key? key_or_attribute
37
+ object[key_or_attribute]
38
+ elsif object.respond_to? key_or_attribute
39
+ object.send key_or_attribute
40
+ end
41
+ end
42
+
43
+ WAYPOINT_FORMAT = [:street,
44
+ :address,
45
+ :city,
46
+ ",",
47
+ :state,
48
+ :province,
49
+ :state_province,
50
+ :country,
51
+ :postal_code]
52
+
53
+ def format_waypoint(waypoint)
54
+ return waypoint if waypoint.instance_of? String
55
+
56
+ if WAYPOINT_FORMAT
57
+ .find_all { |el| el.instance_of? Symbol }
58
+ .any? { |key| has_key_or_attribute?(waypoint, key) }
59
+
60
+ # find all matching elements
61
+ q = WAYPOINT_FORMAT.map do |attr|
62
+ attr.instance_of?(String) ? attr : get_by_key_or_attribute(waypoint, attr)
63
+ end.find_all { |el| el }
64
+
65
+ q.inject('') do |query, el|
66
+ # if it's punctuation or the first character, don't put a space before it
67
+ if el =~ /^[.,!?]$/ or query.length == 0
68
+ "#{query}#{el}"
69
+ else
70
+ "#{query} #{el}"
71
+ end
72
+ end
73
+ else
74
+ # we didn't have any elements matching
75
+ waypoint.to_s
76
+ end
77
+ end
78
+ end
79
+
80
+ class Route
81
+ attr_accessor :response
82
+ attr_accessor :distance
83
+ attr_accessor :distance_unit
84
+ attr_accessor :duration
85
+ attr_accessor :route
86
+
87
+ def initialize(httparty_response)
88
+ @response = httparty_response
89
+
90
+ if @response.response.kind_of? Net::HTTPClientError
91
+ http_code = @response.response.code
92
+ http_message = @response.response.message
93
+ raise "An error has occurred communicating with the Bing Maps service. HTTP Status: #{http_code} (#{http_message})"
94
+ end
95
+
96
+ parse_resource_sets
97
+ end
98
+
99
+ def parse_resource_sets
100
+ resource_sets = @response.parsed_response["resourceSets"]
101
+ raise "No route found." if resource_sets == nil or resource_sets.length == 0
102
+
103
+ resources = resource_sets.first["resources"]
104
+ raise "No route found." if resources == nil or resources.length == 0
105
+
106
+ primary_route = resources.first
107
+
108
+ @distance = primary_route["travelDistance"]
109
+ @distance_unit = primary_route["distanceUnit"].downcase.to_sym
110
+
111
+ @duration = primary_route["travelDuration"]
112
+
113
+ @route = primary_route
114
+ end
115
+ end
116
+ end
data/periplus.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{periplus}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ryan Crum"]
12
+ s.date = %q{2011-06-16}
13
+ s.description = %q{A library that behaves as a client for the Bing Maps REST sdk}
14
+ s.email = %q{ryan.j.crum@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "lib/periplus.rb",
29
+ "periplus.gemspec",
30
+ "spec/request_spec.rb",
31
+ "spec/route_spec.rb",
32
+ "spec/spec_helper.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/thorstadt/periplus}
35
+ s.licenses = ["MIT"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.6.2}
38
+ s.summary = %q{Bing Maps REST Client}
39
+
40
+ if s.respond_to? :specification_version then
41
+ s.specification_version = 3
42
+
43
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
45
+ s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
46
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
47
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
48
+ s.add_development_dependency(%q<rcov>, [">= 0"])
49
+ else
50
+ s.add_dependency(%q<httparty>, [">= 0"])
51
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
52
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
54
+ s.add_dependency(%q<rcov>, [">= 0"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<httparty>, [">= 0"])
58
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,54 @@
1
+ require 'periplus'
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe "Request" do
5
+ it "formats an address hash correctly" do
6
+ req = Periplus::Request.new 'fake_key'
7
+ address_hash = {
8
+ :street => "123 Maple Lane",
9
+ :city => "Beverly Hills",
10
+ :state => "California",
11
+ :country => "US",
12
+ :postal_code => 90210
13
+ }
14
+
15
+ formatted = req.send :format_waypoint, address_hash
16
+
17
+ formatted.should == "123 Maple Lane Beverly Hills, California US 90210"
18
+ end
19
+
20
+ it "hashifies a list of waypoints correctly for the HTTParty query" do
21
+ req = Periplus::Request.new 'fake_key'
22
+
23
+ waypoints = ["New York, NY", "Buffalo, NY", "Louisville, KY"]
24
+ hash = req.send :hashify_waypoints, waypoints
25
+
26
+ hash.should == {
27
+ "wp.1" => "New York, NY",
28
+ "wp.2" => "Buffalo, NY",
29
+ "wp.3" => "Louisville, KY"
30
+ }
31
+ end
32
+
33
+ it "formats an address object correctly" do
34
+ class PeriplusAddress
35
+ attr_accessor :address
36
+ attr_accessor :city
37
+ attr_accessor :state
38
+ attr_accessor :country
39
+ attr_accessor :postal_code
40
+ end
41
+
42
+ address = PeriplusAddress.new
43
+ address.address = "1600 Pennsylvania Ave"
44
+ address.city = "Washington"
45
+ address.state = "DC"
46
+ address.country = "US"
47
+ address.postal_code = 20500
48
+
49
+ req = Periplus::Request.new 'fake key'
50
+ formatted = req.send :format_waypoint, address
51
+
52
+ formatted.should == "1600 Pennsylvania Ave Washington, DC US 20500"
53
+ end
54
+ end
@@ -0,0 +1,57 @@
1
+ require 'periplus'
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe "Route" do
5
+ it "throws an exception if the httparty response is HTTP status 4xx" do
6
+ http_error = Net::HTTPUnauthorized.new "1_1", 401, "Unauthorized"
7
+ response = mock HTTParty::Response, :response => http_error
8
+
9
+ begin
10
+ Periplus::Route.new(response)
11
+ rescue Exception => e
12
+ e.message.should == "An error has occurred communicating with the Bing Maps service. HTTP Status: 401 (Unauthorized)"
13
+ end
14
+ end
15
+
16
+ it "throws an exception if the httparty response contains no routes" do
17
+ http_ok = Net::HTTPOK.new "1_1", 200, "OK"
18
+ empty_resource_sets = {
19
+ "resourceSets" => []
20
+ }
21
+
22
+ empty_single_resource_set = {
23
+ "resourceSets" => [{"resources" => []}]
24
+ }
25
+
26
+ [empty_resource_sets, empty_single_resource_set].each do |parsed_response|
27
+ response = mock HTTParty::Response, :response => http_ok, :parsed_response => parsed_response
28
+
29
+ begin
30
+ Periplus::Route.new(response)
31
+ rescue Exception => e
32
+ e.message.should == "No route found."
33
+ end
34
+ end
35
+ end
36
+
37
+ it "stores shortcut attributes properly" do
38
+ http_ok = Net::HTTPOK.new "1_1", 200, "OK"
39
+ parsed_response = {
40
+ "resourceSets" => [{
41
+ "resources" => [{
42
+ "travelDistance" => 50,
43
+ "travelDuration" => 12345,
44
+ "distanceUnit" => "Mile"
45
+ }]
46
+ }]
47
+ }
48
+
49
+ response = mock HTTParty::Response, :response => http_ok, :parsed_response => parsed_response
50
+ route = Periplus::Route.new response
51
+
52
+ route.distance.should == 50
53
+ route.duration.should == 12345
54
+ route.distance_unit.should == :mile
55
+ route.route.should == parsed_response["resourceSets"].first["resources"].first
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'periplus'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: periplus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Crum
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-16 00:00:00.000000000 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ requirement: &2156329600 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2156329600
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &2156329120 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.4.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *2156329120
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ requirement: &2156328640 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *2156328640
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &2156328160 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.6.2
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *2156328160
59
+ - !ruby/object:Gem::Dependency
60
+ name: rcov
61
+ requirement: &2156327680 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *2156327680
70
+ description: A library that behaves as a client for the Bing Maps REST sdk
71
+ email: ryan.j.crum@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files:
75
+ - LICENSE.txt
76
+ - README.rdoc
77
+ files:
78
+ - .document
79
+ - .rspec
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE.txt
83
+ - README.rdoc
84
+ - Rakefile
85
+ - VERSION
86
+ - lib/periplus.rb
87
+ - periplus.gemspec
88
+ - spec/request_spec.rb
89
+ - spec/route_spec.rb
90
+ - spec/spec_helper.rb
91
+ has_rdoc: true
92
+ homepage: http://github.com/thorstadt/periplus
93
+ licenses:
94
+ - MIT
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ segments:
106
+ - 0
107
+ hash: 3190034002806456688
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 1.6.2
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: Bing Maps REST Client
120
+ test_files: []