azimuth 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +4 -0
  3. data/CONTRIBUTING.md +34 -0
  4. data/LICENSE +20 -0
  5. data/README.md +98 -0
  6. data/Rakefile +42 -0
  7. data/azimuth.gemspec +31 -0
  8. data/lib/azimuth.rb +25 -0
  9. data/lib/azimuth/client.rb +26 -0
  10. data/lib/azimuth/client/route_matrix.rb +38 -0
  11. data/lib/azimuth/configuration.rb +43 -0
  12. data/lib/azimuth/connection.rb +28 -0
  13. data/lib/azimuth/error.rb +45 -0
  14. data/lib/azimuth/request.rb +30 -0
  15. data/lib/azimuth/response/raise_error.rb +18 -0
  16. data/lib/azimuth/version.rb +5 -0
  17. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/behaves_like_a_route_matrix_request/returns_locations_coordinates.yml +87 -0
  18. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/behaves_like_a_route_matrix_request/returns_locations_distances_to_destination.yml +87 -0
  19. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/behaves_like_a_route_matrix_request/returns_locations_driving_times_to_destination.yml +87 -0
  20. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/with_all_to_all_options/it_returns_destination_informations.yml +88 -0
  21. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/with_many_to_one_options/does_not_return_destination_informations.yml +87 -0
  22. data/spec/cassettes/Azimuth_Client_RouteMatrix/_route_matrix/with_no_optionnal_options/does_not_return_destination_informations.yml +87 -0
  23. data/spec/lib/azimuth/client/route_matrix_spec.rb +39 -0
  24. data/spec/lib/azimuth/client_spec.rb +56 -0
  25. data/spec/lib/azimuth/request_spec.rb +11 -0
  26. data/spec/lib/azimuth_spec.rb +32 -0
  27. data/spec/spec_helper.rb +52 -0
  28. data/spec/support/shared_examples/error.rb +15 -0
  29. data/spec/support/shared_examples/route_matrix_request.rb +26 -0
  30. metadata +170 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2bb19f0b0c81b19c9ef79e3e5ecd08850c9c302c
4
+ data.tar.gz: 9d58a7bfda4e2ff8b6a3d822e4e2e016d9f04b90
5
+ SHA512:
6
+ metadata.gz: eafec56b6419352f70e9ffee73cd8ad57428bb38934212d777f2e9ac865b3fec7b6a3b88e95082e849657e59973ed80ecd225c116bdda9e5cec23475d8299e42
7
+ data.tar.gz: 19966e521427518e548a14b9a23663290b505efe5f0bdef8ff94a57f3b2090ef3d8f52ca03644083fd047ec37a1d4099a572dbd825c509a194c20f040ccbb531
@@ -0,0 +1,4 @@
1
+ --no-private
2
+ --quiet
3
+ --markup=markdown
4
+ --exclude lib/azimuth/response
@@ -0,0 +1,34 @@
1
+ # Contributing
2
+
3
+ ## Running the test suite
4
+
5
+ bundle exec rake spec
6
+
7
+ ### Code quality
8
+
9
+ Code quality is checked with [cane](https://github.com/square/cane) configured in `Rakefile`.
10
+
11
+ Build fails if code quality thresholds **are not met**.
12
+
13
+ ### Code coverage
14
+
15
+ When running the test suite a test coverage report is generated with [SimpleCov](https://github.com/colszowka/simplecov) in `coverage/index.html`.
16
+
17
+ Build fails if coverage is below **99%**.
18
+
19
+ ## Writing new tests
20
+ Azimuth uses [VCR](https://github.com/vcr/vcr) for recording and playing back API fixtures (in `spec/cassettes`) during test runs.
21
+
22
+ If you need to record new cassettes you have to provide your MapQuest API key in `ENV['MAP_QUEST_API_KEY']` (stripped automaticaly from the cassette before being saved on disk).
23
+
24
+ ## Documentation
25
+
26
+ Documentation is generated with [YARD](http://yardoc.org/).
27
+
28
+ ## Workflow
29
+
30
+ 1. Fork [Azimuth](https://github.com/sush/azimuth)
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create a new Pull Request
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) [2014] [Aylic Petit]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,98 @@
1
+ # Azimuth
2
+
3
+ Simple Ruby wrapper for the [MapQuest Directions API](http://www.mapquestapi.com/directions).
4
+
5
+ **Current version**: [![Gem Version](https://badge.fury.io/rb/azimuth.png)](http://badge.fury.io/rb/azimuth)
6
+
7
+ **Build status**:        [![Build Status](https://secure.travis-ci.org/sush/azimuth.png?branch=master)](http://travis-ci.org/sush/azimuth)
8
+
9
+ **Code metrics**:
10
+      [![Code Climate](https://codeclimate.com/github/sush/azimuth.png)](https://codeclimate.com/github/sush/azimuth)
11
+ [![Coverage Status](https://coveralls.io/repos/sush/azimuth/badge.png?branch=master)](https://coveralls.io/r/sush/azimuth?branch=master)
12
+
13
+ **Ruby support**:
14
+
15
+ - 1.9.2
16
+ - 1.9.3
17
+ - 2.0.0
18
+ - 2.1.0
19
+
20
+ ## Installation
21
+
22
+ Install via Rubygems
23
+
24
+ gem install azimuth
25
+
26
+ or add to your Gemfile
27
+
28
+ gem 'azimuth'
29
+
30
+ ### Configuration
31
+
32
+ API methods are available as module methods
33
+
34
+ ```ruby
35
+ Azimuth.configure do |c|
36
+ c.api_endpoint = 'http://newendpoint/'
37
+ c.api_key = 'YOUR_MAP_QUEST_API_KEY'
38
+ end
39
+ ```
40
+
41
+ or as client instance methods
42
+
43
+ ```ruby
44
+ Azimuth::Client.new(
45
+ api_endpoint: 'http://newendpoint/',
46
+ api_key: 'YOUR_MAP_QUEST_API_KEY',
47
+ )
48
+ ```
49
+
50
+ ## Authentication
51
+
52
+ Azimuth only supports authentication via an API key.
53
+
54
+ You can request one following these [steps](http://developer.mapquest.com/web/products/open).
55
+
56
+ ## Usage
57
+
58
+
59
+ ```ruby
60
+ locations = Azimuth.route_matrix(["48.843079, 2.314442", "48.869061, 2.383329"])
61
+ p locations
62
+ # => [{"latitude"=>48.869061, "longitude"=>2.383329, "time"=>0, "distance"=>0}]
63
+
64
+ # etc…
65
+ ```
66
+
67
+ ## Features
68
+
69
+ Azimuth supports the following MapQuest Directions API methods:
70
+
71
+ - [Route Matrix](http://www.mapquestapi.com/directions/#matrix)
72
+
73
+ Complete Azimuth public API's documentation [here](http://rubydoc.info/gems/azimuth/frames).
74
+
75
+
76
+ ## Similar libraries
77
+
78
+ - [mapquest](https://github.com/ggordan/mapquest)
79
+
80
+ ## Versioning
81
+ Azimuth follows the principles of [semantic versioning](http://semver.org).
82
+
83
+ 1. Patch level releases contain only bug fixes.
84
+ 2. Minor releases contain backward-compatible new features.
85
+ 3. Major new releases contain backwards-incompatible changes to the public API.
86
+
87
+ ## Contributing
88
+
89
+ Pull Requests are welcome !
90
+
91
+ Please refer to the [Contributing guide](https://github.com/sush/azimuth/blob/master/CONTRIBUTING.md) for more details on how to run the test suite and to contribute.
92
+
93
+
94
+ ## Copyright
95
+
96
+ Copyright © 2014 Aylic Petit
97
+
98
+ Released under the terms of the MIT licence. See the [LICENSE](https://github.com/sush/azimuth/blob/master/LICENSE) file for more details.
@@ -0,0 +1,42 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ begin
8
+ require 'cane/rake_task'
9
+
10
+ desc 'Run cane to check quality metrics'
11
+ Cane::RakeTask.new(:quality) do |cane|
12
+ cane.add_threshold 'coverage/.last_run.json', :>=, 99
13
+ cane.abc_glob = '{lib}/**/*.rb'
14
+ cane.abc_max = 15
15
+ cane.style_measure = 105
16
+ cane.style_exclude = %w[spec/spec_helper.rb]
17
+ cane.canefile = '.cane'
18
+ end
19
+ rescue LoadError
20
+ end
21
+
22
+ namespace :doc do
23
+ begin
24
+ require 'yard'
25
+
26
+ YARD::Rake::YardocTask.new do |task|
27
+ task.files = ['README.md', 'LICENSE.md', 'lib/**/*.rb']
28
+ task.options = [
29
+ '--output-dir', 'doc/yard',
30
+ '--markup', 'markdown'
31
+ ]
32
+ end
33
+ rescue LoadError
34
+ end
35
+ end
36
+
37
+ Rake::Task[:spec].enhance do
38
+ Rake::Task[:quality].invoke
39
+ end
40
+
41
+ task :test => :spec
42
+ task :default => :spec
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'azimuth/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'azimuth'
8
+ gem.version = Azimuth::VERSION.dup
9
+ gem.license = 'MIT'
10
+
11
+ gem.summary = %q{MapQuest Direction API Ruby wrapper}
12
+ gem.description = %q{Simple Ruby wrapper for the MapQuest Direction API.}
13
+ gem.homepage = 'https://github.com/sush/azimuth'
14
+
15
+ gem.authors = ['Aylic Petit']
16
+ gem.email = ['sush@users.noreply.github.com']
17
+
18
+ gem.required_ruby_version = '>= 1.9.2'
19
+
20
+ gem.files = %w[.yardopts LICENSE README.md CONTRIBUTING.md Rakefile azimuth.gemspec]
21
+ gem.files += Dir.glob('{spec,lib}/**/*.rb')
22
+ gem.require_paths = ['lib']
23
+ gem.test_files = Dir.glob('spec/**/*')
24
+
25
+ gem.add_development_dependency 'bundler', '~> 1.0'
26
+ gem.add_dependency 'faraday', '~> 0.8.9'
27
+ gem.add_dependency 'faraday_middleware', '~> 0.9.0'
28
+ gem.add_dependency 'hashie', '~>2.0.5'
29
+ gem.add_dependency 'json', '~>1.8.1'
30
+ gem.add_dependency 'multi_json', '~>1.8.4'
31
+ end
@@ -0,0 +1,25 @@
1
+ require 'azimuth/configuration'
2
+ require 'azimuth/client'
3
+
4
+ # Ruby wrapper for MapQuest Directions API
5
+ module Azimuth
6
+ extend Configuration
7
+
8
+ class << self
9
+ # Delegates to Azimuth::Client#new
10
+ def new(options={})
11
+ Azimuth::Client.new(options)
12
+ end
13
+
14
+ # @private
15
+ def method_missing(method, *args, &block)
16
+ return super unless new.respond_to?(method)
17
+ new.send(method, *args, &block)
18
+ end
19
+
20
+ # @private
21
+ def respond_to?(method, include_private=false)
22
+ new.respond_to?(method, include_private) || super(method, include_private)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ require 'azimuth/connection'
2
+ require 'azimuth/request'
3
+
4
+ require 'azimuth/client/route_matrix'
5
+
6
+ module Azimuth
7
+ # Client for the MapQuest Directions API
8
+ #
9
+ # @see http://www.mapquestapi.com/directions
10
+ class Client
11
+ attr_accessor(*Configuration::VALID_OPTIONS)
12
+
13
+ def initialize(options={})
14
+ options = Azimuth.options.merge(options)
15
+
16
+ Configuration::VALID_OPTIONS.each do |key|
17
+ send("#{key}=", options[key])
18
+ end
19
+ end
20
+
21
+ include Azimuth::Connection
22
+ include Azimuth::Request
23
+
24
+ include Azimuth::Client::RouteMatrix
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ module Azimuth
2
+ class Client
3
+ # Methods for the Route Matrix API
4
+ #
5
+ # @see http://www.mapquestapi.com/directions/#matrix
6
+ module RouteMatrix
7
+ # Get calculation of the distances and driving times between locations.
8
+ # @param locations [Array] the locations
9
+ # @param options [Hash] optional parameters
10
+ # @option options [Hash] :manyToOne parameter
11
+ # @option options [Hash] :allToAll parameter
12
+ # @return [Hashie::Mash] the locations and their distance and traveling time
13
+ # @see http://www.mapquestapi.com/directions/#matrix
14
+ # @example
15
+ # Azimuth.route_matrix(['48.843079, 2.314442', '48.869061, 2.383329']
16
+ def route_matrix(locations, options={})
17
+ parameters = { locations: locations, options: options }
18
+
19
+ format_response(post('routematrix', parameters))
20
+ end
21
+
22
+ private
23
+
24
+ def format_response(response)
25
+ response.locations.delete_at(0) unless response.allToAll
26
+
27
+ response.locations.each_with_index.map do |location, i|
28
+ Hashie::Mash.new(
29
+ latitude: location.latLng.lat,
30
+ longitude: location.latLng.lng,
31
+ time: response.time[i],
32
+ distance: response.distance[i]
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ module Azimuth
2
+ # Methods for Azimuth configuration
3
+ module Configuration
4
+ # Configurable options
5
+ VALID_OPTIONS = [
6
+ :api_endpoint,
7
+ :api_key,
8
+ ].freeze
9
+
10
+ # Default MapQuest Directions API endpoint
11
+ DEFAULT_API_ENDPOINT = 'http://www.mapquestapi.com/directions/v2/'
12
+
13
+ attr_accessor(*VALID_OPTIONS)
14
+
15
+ # @private
16
+ def self.extended(base_obj)
17
+ base_obj.initialize_default_options
18
+ end
19
+
20
+ # Set configuration options using a block
21
+ def configure
22
+ yield self
23
+ end
24
+
25
+ # Default options
26
+ def options
27
+ VALID_OPTIONS.inject({}){ |o, k| o.merge!(k => send(k)) }
28
+ end
29
+
30
+ # Initialize default options
31
+ def initialize_default_options
32
+ self.api_endpoint = DEFAULT_API_ENDPOINT
33
+ self.api_key = nil
34
+ end
35
+
36
+ # Reset configuration options to default values
37
+ def reset!
38
+ initialize_default_options
39
+
40
+ self
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ require 'faraday_middleware'
2
+ require 'azimuth/response/raise_error'
3
+
4
+ module Azimuth
5
+ # Faraday connection methods
6
+ module Connection
7
+ private
8
+
9
+ def connection
10
+ options = {
11
+ ssl: { verify: false },
12
+ url: self.api_endpoint,
13
+ }
14
+
15
+ connection = Faraday.new(options) do |conn|
16
+ conn.response(:mashify)
17
+ conn.response(:json, content_type: /\bjson$/)
18
+
19
+ conn.use(Azimuth::Response::RaiseError)
20
+ conn.use(FaradayMiddleware::FollowRedirects, limit: 3)
21
+
22
+ conn.adapter(Faraday.default_adapter)
23
+ end
24
+
25
+ connection
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ require 'multi_json'
2
+
3
+ module Azimuth
4
+ # Custom error class
5
+ class Error < StandardError
6
+ # Returns the Error based on status and response message.
7
+ #
8
+ # @param [Hash] response HTTP response
9
+ # @return [Azimuth::Error]
10
+ def self.from_response(response)
11
+ parsed_response_info = ::MultiJson.load(response[:body])['info']
12
+
13
+ status_code = parsed_response_info['statuscode']
14
+
15
+ return if status_code == 0
16
+
17
+ if error_message = parsed_response_info['messages']
18
+ error_message = error_message.join(' ')
19
+ end
20
+
21
+ case status_code
22
+ when 400
23
+ raise Azimuth::ErrorWithInput, error_message
24
+ when 403
25
+ raise Azimuth::KeyRelatedError, error_message
26
+ when 500
27
+ raise Azimuth::UnknownError, error_message
28
+ when 600...699
29
+ raise Azimuth::OtherError, error_message
30
+ end
31
+ end
32
+ end
33
+
34
+ # Raised when API returns 400 error code
35
+ class ErrorWithInput < Error; end
36
+
37
+ # Raised when API returns 403 error code
38
+ class KeyRelatedError < Error; end
39
+
40
+ # Raised when API returns 500 error code
41
+ class UnknownError < Error; end
42
+
43
+ # Raised when API returns error code between 600 and 699
44
+ class OtherError < Error; end
45
+ end