google_maps_api-directions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c5ab55ac8c65193c48ef84b188aad24fb9cc4339
4
+ data.tar.gz: 64ea3b0da7201bd113dbf9ded5c00150ae22c632
5
+ SHA512:
6
+ metadata.gz: b946bac2ceb2942a92fcb229dcac1e0ba070434ed4d04f37adab6427d5e204626b8d3050ed0aee38d6175f01b32a844684f05f21eee0f5eaa8bb4564da188585
7
+ data.tar.gz: d1955b2f858213d5665d90dccc8a903a49415934ce19544fbcd3c536b87ff0ec4050fb01dae526c0849db39ad8d3f8e546a57e4ebc6675ef5ad9c48862298dad
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in google_maps_api-directions.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Felipe Zavan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # GoogleMapsAPI::Directions
2
+
3
+ This is a wrapper around the Google Maps Directions API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'google_maps_api-directions'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install google_maps_api-directions
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ GoogleMapsAPI::Directions.route(origin, destination, options = {})
23
+ ```
24
+
25
+ Origin and destination can be an a string or anything that supports ```to_ary```.
26
+ Options is a *Symbols* Hash with optional parameters. (See https://developers.google.com/maps/documentation/directions/#RequestParameters for more information).
27
+
28
+ ### Examples:
29
+
30
+ ```ruby
31
+ origin = "350, 5th Ave, NY"
32
+ destination = [40.777552, -73.954732]
33
+ options = {:language => 'pt'}
34
+ GoogleMapsAPI::Directions.route(origin, destination, options)
35
+ # => #<GoogleMapsAPI::Directions::Response:0x00000001f2b510...>
36
+ ```
37
+
38
+ The ```GoogleMapsAPI::Directions::Response``` mimics the API JSON structure.
39
+
40
+ If you wish to call ```#coordinates``` on ```GoogleMapsAPI::Directions::EncodedPolyline``` objects,
41
+ you will need to install the https://rubygems.org/gems/polylines gem.
42
+
43
+ ## Contributing
44
+
45
+ I am new to Ruby and Testing. We need better specs.
46
+
47
+ 1. Fork it ( https://github.com/zavan/google_maps_api-directions/fork )
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create a new Pull Request
52
+
53
+ ### Important
54
+
55
+ * Do not touch the version;
56
+ * Write specs for new features;
57
+ * Be independent of Rails stuff;
58
+ * All specs must pass.
59
+
60
+ ## Also see
61
+
62
+ * [http://github.com/zavan/google_maps_api-core](http://github.com/zavan/google_maps_api-core)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'google_maps_api/directions/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "google_maps_api-directions"
8
+ spec.version = GoogleMapsAPI::Directions::VERSION
9
+ spec.authors = ["Felipe Zavan"]
10
+ spec.email = ["zavan@outlook.com"]
11
+ spec.summary = %q{Wrapper around the Google Maps Directions API.}
12
+ spec.homepage = "https://github.com/zavan/google_maps_api-directions"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec", ">= 3.0.0.beta2", "< 4"
23
+
24
+ spec.add_dependency "google_maps_api-core", "~> 0"
25
+ end
@@ -0,0 +1,19 @@
1
+ require "google_maps_api/directions/version"
2
+ require "google_maps_api/core"
3
+ require "google_maps_api/directions/request"
4
+ require "google_maps_api/directions/route"
5
+ require "google_maps_api/directions/bounds"
6
+ require "google_maps_api/directions/leg"
7
+ require "google_maps_api/directions/step"
8
+ require "google_maps_api/directions/encoded_polyline"
9
+ require "google_maps_api/directions/response"
10
+ require "google_maps_api/directions/exceptions"
11
+
12
+ module GoogleMapsAPI
13
+ module Directions
14
+ def self.route(origin, destination, options = {})
15
+ request = Request.build(origin, destination, options)
16
+ request.perform
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ class GoogleMapsAPI::Directions::Bounds
2
+ attr_reader :northeast, :southwest
3
+
4
+ def initialize(northeast, southwest)
5
+ @northeast = northeast
6
+ @southwest = southwest
7
+ self
8
+ end
9
+
10
+ def self.from_hash(hash)
11
+ northeast = build_coordinate(hash["northeast"])
12
+ southwest = build_coordinate(hash["southwest"])
13
+ self.new(northeast, southwest)
14
+ end
15
+
16
+ private
17
+
18
+ def self.build_coordinate(hash)
19
+ GoogleMapsAPI::Core::Coordinate.from_hash(hash)
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ class GoogleMapsAPI::Directions::EncodedPolyline
2
+ attr_reader :encoded
3
+
4
+ def initialize(encoded)
5
+ @encoded = encoded
6
+ end
7
+
8
+ def coordinates
9
+ @coordinates ||= decode
10
+ @coordinates
11
+ end
12
+
13
+ def to_s
14
+ encoded
15
+ end
16
+
17
+ private
18
+
19
+ def decode
20
+ begin
21
+ require "polylines" unless defined?(Polylines)
22
+ array = Polylines::Decoder.decode_polyline(encoded)
23
+ return array.collect do |c|
24
+ GoogleMapsAPI::Core::Coordinate.from_array(c)
25
+ end
26
+ rescue LoadError
27
+ raise "You need to install and require the 'polylines' (https://rubygems.org/gems/polylines) gem in your Gemfile if you want to use this method"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,5 @@
1
+ class GoogleMapsAPI::Directions::Error < StandardError; end
2
+
3
+ class GoogleMapsAPI::Directions::ResponseError < GoogleMapsAPI::Directions::Error
4
+ attr_accessor :response
5
+ end
@@ -0,0 +1,46 @@
1
+ require 'google_maps_api/directions/leg_and_step_common_builders'
2
+
3
+ class GoogleMapsAPI::Directions::Leg
4
+ extend GoogleMapsAPI::Directions::LegAndStepCommonBuilders
5
+
6
+ attr_reader :distance, :duration, :end_address, :end_location,
7
+ :start_address, :start_location, :steps, :via_waypoint
8
+
9
+ def initialize(
10
+ distance, duration, end_address, end_location,
11
+ start_address, start_location, steps, via_waypoint
12
+ )
13
+ @distance = distance
14
+ @duration = duration
15
+ @end_address = end_address
16
+ @end_location = end_location
17
+ @start_address = start_address
18
+ @start_location = start_location
19
+ @steps = steps
20
+ @via_waypoint = via_waypoint
21
+ end
22
+
23
+ def self.from_hash(hash)
24
+ distance = build_distance(hash)
25
+ duration = build_duration(hash)
26
+ end_address = hash["end_address"]
27
+ end_location = build_coordinate(hash["end_location"])
28
+ start_address = hash["start_address"]
29
+ start_location = build_coordinate(hash["start_location"])
30
+ steps = build_steps(hash)
31
+ via_waypoint = hash["via_waypoint"]
32
+
33
+ self.new(
34
+ distance, duration, end_address, end_location,
35
+ start_address, start_location, steps, via_waypoint
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def self.build_steps(hash)
42
+ hash["steps"].collect do |s|
43
+ GoogleMapsAPI::Directions::Step.from_hash(s)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ module GoogleMapsAPI::Directions::LegAndStepCommonBuilders
2
+ def build_distance(hash)
3
+ GoogleMapsAPI::Core::Distance.from_hash(hash["distance"])
4
+ end
5
+
6
+ def build_duration(hash)
7
+ GoogleMapsAPI::Core::Duration.from_hash(hash["duration"])
8
+ end
9
+
10
+ def build_coordinate(hash)
11
+ GoogleMapsAPI::Core::Coordinate.from_hash(hash)
12
+ end
13
+ end
@@ -0,0 +1,82 @@
1
+ require "net/http"
2
+
3
+ class GoogleMapsAPI::Directions::Request
4
+ BASE_PATH = "maps.googleapis.com/maps/api/directions/json"
5
+
6
+ attr_accessor :origin, :destination, :options, :http_adapter
7
+
8
+ def initialize(origin, destination, options = {})
9
+ origin = origin.to_ary.join(",") if origin.respond_to?(:to_ary)
10
+ destination = destination.to_ary.join(",") if destination.respond_to?(:to_ary)
11
+ @origin = origin
12
+ @destination = destination
13
+ @options = default_options.merge(options)
14
+ @http_adapter = nil
15
+ end
16
+
17
+ def self.build(origin, destination, options = {})
18
+ self.new(origin, destination, options)
19
+ end
20
+
21
+ def perform
22
+ response = http_adapter.get_response(uri)
23
+ if response.is_a?(Net::HTTPSuccess)
24
+ return GoogleMapsAPI::Directions::Response.from_json(response.body)
25
+ else
26
+ msg = "The response was not successful (200). Call #response for datails."
27
+ exception = GoogleMapsAPI::Directions::ResponseError.new(msg)
28
+ exception.response = response
29
+ raise exception
30
+ end
31
+ end
32
+
33
+ def uri
34
+ uri = URI("#{scheme}://#{BASE_PATH}")
35
+ query = prepared_options.merge({origin: origin, destination: destination})
36
+ uri.query = URI.encode_www_form(query)
37
+ uri
38
+ end
39
+
40
+ def scheme
41
+ options[:https] ? "https" : "http"
42
+ end
43
+
44
+ def http_adapter
45
+ @http_adapter || Net::HTTP
46
+ end
47
+
48
+ private
49
+
50
+ def default_options
51
+ {
52
+ sensor: false,
53
+ mode: "driving",
54
+ language: "en",
55
+ units: "metric",
56
+ region: "us"
57
+ }
58
+ end
59
+
60
+ def prepared_options
61
+ options = self.options.dup
62
+ options[:departure_time] = time_or_date_to_unix(options[:departure_time])
63
+ options[:arrival_time] = time_or_date_to_unix(options[:arrival_time])
64
+
65
+ if options[:waypoints].respond_to?(:collect)
66
+ waypoints = options[:waypoints].collect do |w|
67
+ w.respond_to?(:to_ary) ? w.to_ary.join(",") : w
68
+ end
69
+
70
+ options[:waypoints] = waypoints.join("|")
71
+ end
72
+
73
+ options.delete_if { |key, value| value.to_s.strip.empty? }
74
+ options
75
+ end
76
+
77
+ def time_or_date_to_unix(time_or_date)
78
+ return time_or_date.to_i if time_or_date.is_a?(Time)
79
+ return time_or_date.to_time.to_i if time_or_date.is_a?(Date)
80
+ time_or_date
81
+ end
82
+ end
@@ -0,0 +1,29 @@
1
+ require "google_maps_api/directions/route"
2
+ require "json"
3
+
4
+ class GoogleMapsAPI::Directions::Response
5
+ attr_reader :routes, :status
6
+
7
+ def initialize(routes, status)
8
+ @routes = routes
9
+ @status = status
10
+ end
11
+
12
+ def self.from_json(json)
13
+ parsed_json = parse_json(json)
14
+ routes = build_routes(parsed_json)
15
+ self.new(routes, parsed_json['status'])
16
+ end
17
+
18
+ private
19
+
20
+ def self.parse_json(json)
21
+ JSON.parse(json)
22
+ end
23
+
24
+ def self.build_routes(parsed_json)
25
+ parsed_json['routes'].collect do |r|
26
+ GoogleMapsAPI::Directions::Route.from_hash(r)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ class GoogleMapsAPI::Directions::Route
2
+ attr_reader :bounds, :copyrights, :legs,
3
+ :overview_polyline, :summary,
4
+ :warnings, :waypoint_order
5
+
6
+ def initialize(
7
+ bounds, copyrights, legs,
8
+ overview_polyline, summary,
9
+ warnings, waypoint_order
10
+ )
11
+ @bounds = bounds
12
+ @copyrights = copyrights
13
+ @legs = legs
14
+ @overview_polyline = overview_polyline
15
+ @summary = summary
16
+ @warnings = warnings
17
+ @waypoint_order = waypoint_order
18
+ end
19
+
20
+ def self.from_hash(hash)
21
+ bounds = build_bounds(hash)
22
+ copyrights = hash["copyrights"]
23
+ legs = build_legs(hash)
24
+ overview_polyline = build_overview_polyline(hash)
25
+ summary = hash["summary"]
26
+ warnings = hash["warnings"]
27
+ waypoint_order = hash["waypoint_order"]
28
+
29
+ self.new(
30
+ bounds, copyrights, legs,
31
+ overview_polyline, summary,
32
+ warnings, waypoint_order
33
+ )
34
+ end
35
+
36
+ private
37
+
38
+ def self.build_bounds(hash)
39
+ GoogleMapsAPI::Directions::Bounds.from_hash(hash["bounds"])
40
+ end
41
+
42
+ def self.build_legs(hash)
43
+ hash["legs"].collect do |l|
44
+ GoogleMapsAPI::Directions::Leg.from_hash(l)
45
+ end
46
+ end
47
+
48
+ def self.build_overview_polyline(hash)
49
+ GoogleMapsAPI::Directions::EncodedPolyline.new(hash["overview_polyline"]["points"])
50
+ end
51
+ end
@@ -0,0 +1,45 @@
1
+ require 'google_maps_api/directions/leg_and_step_common_builders'
2
+
3
+ class GoogleMapsAPI::Directions::Step
4
+ extend GoogleMapsAPI::Directions::LegAndStepCommonBuilders
5
+
6
+ attr_reader :distance, :duration, :end_location,
7
+ :start_location, :html_instructions,
8
+ :polyline, :travel_mode
9
+
10
+ def initialize(
11
+ distance, duration, end_location,
12
+ start_location, html_instructions,
13
+ polyline, travel_mode
14
+ )
15
+ @distance = distance
16
+ @duration = duration
17
+ @end_location = end_location
18
+ @start_location = start_location
19
+ @html_instructions = html_instructions
20
+ @polyline = polyline
21
+ @travel_mode = travel_mode
22
+ end
23
+
24
+ def self.from_hash(hash)
25
+ distance = build_distance(hash)
26
+ duration = build_duration(hash)
27
+ end_location = build_coordinate(hash["end_location"])
28
+ start_location = build_coordinate(hash["start_location"])
29
+ html_instructions = hash["html_instructions"]
30
+ polyline = build_polyline(hash)
31
+ travel_mode = hash["travel_mode"]
32
+
33
+ self.new(
34
+ distance, duration, end_location,
35
+ start_location, html_instructions,
36
+ polyline, travel_mode
37
+ )
38
+ end
39
+
40
+ private
41
+
42
+ def self.build_polyline(hash)
43
+ GoogleMapsAPI::Directions::EncodedPolyline.new(hash["polyline"]["points"])
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ module GoogleMapsAPI
2
+ module Directions
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/json_response"
3
+
4
+ describe GoogleMapsAPI::Directions::Bounds do
5
+ include_context "json response"
6
+
7
+ subject { GoogleMapsAPI::Directions::Bounds }
8
+
9
+ describe ".from_hash" do
10
+ it "returns a new bounds object" do
11
+ expect(subject.from_hash(parsed_json["routes"].first["bounds"])).to be_a(subject)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ require "json"
2
+
3
+ shared_context "json response" do
4
+ let(:json) { File.read("#{File.dirname(__FILE__)}/response_mock.json") }
5
+ let(:parsed_json) { JSON.parse(json) }
6
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/json_response"
3
+
4
+ describe GoogleMapsAPI::Directions::Leg do
5
+ include_context "json response"
6
+
7
+ subject { GoogleMapsAPI::Directions::Leg }
8
+
9
+ describe ".from_hash" do
10
+ it "returns a new leg" do
11
+ expect(subject.from_hash(parsed_json["routes"].first["legs"].first)).to be_a(subject)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ shared_context "request lets" do
2
+ let(:origin) { "350, 5th Avenue, New York" }
3
+ let(:destination) { "100, 4th Avenue, New York" }
4
+ let(:options) { {} }
5
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/request_lets"
3
+
4
+ describe GoogleMapsAPI::Directions::Request do
5
+
6
+ include_context "request lets"
7
+
8
+ subject { GoogleMapsAPI::Directions::Request.new(origin, destination, options) }
9
+
10
+ describe ".build" do
11
+ subject { GoogleMapsAPI::Directions::Request }
12
+
13
+ it "builds a new request" do
14
+ expect(subject.build(origin, destination, options)).to be_a(subject)
15
+ end
16
+ end
17
+
18
+ describe "#perform" do
19
+ it "returns a response" do
20
+ expect(subject.perform).to be_a(GoogleMapsAPI::Directions::Response)
21
+ end
22
+
23
+ it "raises a ResponseError if the response is not successful" do
24
+ allow(subject.http_adapter).to receive(:get_response).and_return(false)
25
+ expect { subject.perform }.to raise_error(GoogleMapsAPI::Directions::ResponseError)
26
+ end
27
+ end
28
+
29
+ describe "#uri" do
30
+ it "returns a URI" do
31
+ expect(subject.uri).to be_a(URI)
32
+ end
33
+ end
34
+
35
+ describe "#scheme" do
36
+ context "when https option is true" do
37
+ subject { GoogleMapsAPI::Directions::Request.new(origin, destination, {https: true}) }
38
+
39
+ it "returns 'https'" do
40
+ expect(subject.scheme).to eq('https')
41
+ end
42
+ end
43
+
44
+ context "when https option is false" do
45
+ subject { GoogleMapsAPI::Directions::Request.new(origin, destination, {https: false}) }
46
+
47
+ it "returns 'http'" do
48
+ expect(subject.scheme).to eq('http')
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,306 @@
1
+ {
2
+ "routes" : [
3
+ {
4
+ "bounds" : {
5
+ "northeast" : {
6
+ "lat" : 40.7660501,
7
+ "lng" : -73.9777149
8
+ },
9
+ "southwest" : {
10
+ "lat" : 40.7415437,
11
+ "lng" : -73.99280299999999
12
+ }
13
+ },
14
+ "copyrights" : "Map data ©2014 Google, Sanborn",
15
+ "legs" : [
16
+ {
17
+ "distance" : {
18
+ "text" : "1.0 mi",
19
+ "value" : 1540
20
+ },
21
+ "duration" : {
22
+ "text" : "4 mins",
23
+ "value" : 216
24
+ },
25
+ "end_address" : "200 5th Avenue, New York, NY 10010, USA",
26
+ "end_location" : {
27
+ "lat" : 40.7419552,
28
+ "lng" : -73.9893319
29
+ },
30
+ "start_address" : "350 5th Avenue, New York, NY 10118, USA",
31
+ "start_location" : {
32
+ "lat" : 40.7479836,
33
+ "lng" : -73.9848799
34
+ },
35
+ "steps" : [
36
+ {
37
+ "distance" : {
38
+ "text" : "0.5 mi",
39
+ "value" : 819
40
+ },
41
+ "duration" : {
42
+ "text" : "1 min",
43
+ "value" : 81
44
+ },
45
+ "end_location" : {
46
+ "lat" : 40.7415437,
47
+ "lng" : -73.98959259999999
48
+ },
49
+ "html_instructions" : "Head \u003cb\u003esouthwest\u003c/b\u003e on \u003cb\u003e5th Ave\u003c/b\u003e toward \u003cb\u003eE 33rd St\u003c/b\u003e",
50
+ "polyline" : {
51
+ "points" : "{quwFndqbMh@`@|BzAxBvAzBvAzBzAxBzAfBhAPL|BzA|BvAn@`@XRXRJFdAp@RPr@d@"
52
+ },
53
+ "start_location" : {
54
+ "lat" : 40.7479836,
55
+ "lng" : -73.9848799
56
+ },
57
+ "travel_mode" : "DRIVING"
58
+ },
59
+ {
60
+ "distance" : {
61
+ "text" : "0.2 mi",
62
+ "value" : 309
63
+ },
64
+ "duration" : {
65
+ "text" : "1 min",
66
+ "value" : 38
67
+ },
68
+ "end_location" : {
69
+ "lat" : 40.7428904,
70
+ "lng" : -73.99280299999999
71
+ },
72
+ "html_instructions" : "Turn \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eW 23rd St\u003c/b\u003e",
73
+ "maneuver" : "turn-right",
74
+ "polyline" : {
75
+ "points" : "sitwF|arbMsDhLyAvE"
76
+ },
77
+ "start_location" : {
78
+ "lat" : 40.7415437,
79
+ "lng" : -73.98959259999999
80
+ },
81
+ "travel_mode" : "DRIVING"
82
+ },
83
+ {
84
+ "distance" : {
85
+ "text" : "279 ft",
86
+ "value" : 85
87
+ },
88
+ "duration" : {
89
+ "text" : "1 min",
90
+ "value" : 26
91
+ },
92
+ "end_location" : {
93
+ "lat" : 40.7435581,
94
+ "lng" : -73.9923115
95
+ },
96
+ "html_instructions" : "Take the 2nd \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eAvenue of the Americas\u003c/b\u003e",
97
+ "polyline" : {
98
+ "points" : "artwF~urbMeCaB"
99
+ },
100
+ "start_location" : {
101
+ "lat" : 40.7428904,
102
+ "lng" : -73.99280299999999
103
+ },
104
+ "travel_mode" : "DRIVING"
105
+ },
106
+ {
107
+ "distance" : {
108
+ "text" : "0.2 mi",
109
+ "value" : 327
110
+ },
111
+ "duration" : {
112
+ "text" : "1 min",
113
+ "value" : 71
114
+ },
115
+ "end_location" : {
116
+ "lat" : 40.7419552,
117
+ "lng" : -73.9893319
118
+ },
119
+ "html_instructions" : "Take the 1st \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eW 24th St\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003eDestination will be on the right\u003c/div\u003e",
120
+ "polyline" : {
121
+ "points" : "gvtwF|rrbMvFmQDE@CBCFAD?F?d@H"
122
+ },
123
+ "start_location" : {
124
+ "lat" : 40.7435581,
125
+ "lng" : -73.9923115
126
+ },
127
+ "travel_mode" : "DRIVING"
128
+ }
129
+ ],
130
+ "via_waypoint" : []
131
+ },
132
+ {
133
+ "distance" : {
134
+ "text" : "2.5 mi",
135
+ "value" : 4090
136
+ },
137
+ "duration" : {
138
+ "text" : "11 mins",
139
+ "value" : 651
140
+ },
141
+ "end_address" : "100 West 56th Street, New York, NY 10019, USA",
142
+ "end_location" : {
143
+ "lat" : 40.7636538,
144
+ "lng" : -73.9777149
145
+ },
146
+ "start_address" : "200 5th Avenue, New York, NY 10010, USA",
147
+ "start_location" : {
148
+ "lat" : 40.7419552,
149
+ "lng" : -73.9893319
150
+ },
151
+ "steps" : [
152
+ {
153
+ "distance" : {
154
+ "text" : "167 ft",
155
+ "value" : 51
156
+ },
157
+ "duration" : {
158
+ "text" : "1 min",
159
+ "value" : 13
160
+ },
161
+ "end_location" : {
162
+ "lat" : 40.7415437,
163
+ "lng" : -73.98959259999999
164
+ },
165
+ "html_instructions" : "Head \u003cb\u003esouth\u003c/b\u003e on \u003cb\u003eW 24th St\u003c/b\u003e toward \u003cb\u003e5th Ave\u003c/b\u003e",
166
+ "polyline" : {
167
+ "points" : "gltwFh`rbMF@VJr@d@"
168
+ },
169
+ "start_location" : {
170
+ "lat" : 40.7419552,
171
+ "lng" : -73.9893319
172
+ },
173
+ "travel_mode" : "DRIVING"
174
+ },
175
+ {
176
+ "distance" : {
177
+ "text" : "0.2 mi",
178
+ "value" : 309
179
+ },
180
+ "duration" : {
181
+ "text" : "1 min",
182
+ "value" : 38
183
+ },
184
+ "end_location" : {
185
+ "lat" : 40.7428904,
186
+ "lng" : -73.99280299999999
187
+ },
188
+ "html_instructions" : "Take the 1st \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eW 23rd St\u003c/b\u003e",
189
+ "polyline" : {
190
+ "points" : "sitwF|arbMsDhLyAvE"
191
+ },
192
+ "start_location" : {
193
+ "lat" : 40.7415437,
194
+ "lng" : -73.98959259999999
195
+ },
196
+ "travel_mode" : "DRIVING"
197
+ },
198
+ {
199
+ "distance" : {
200
+ "text" : "1.1 mi",
201
+ "value" : 1762
202
+ },
203
+ "duration" : {
204
+ "text" : "4 mins",
205
+ "value" : 234
206
+ },
207
+ "end_location" : {
208
+ "lat" : 40.7567653,
209
+ "lng" : -73.98270230000001
210
+ },
211
+ "html_instructions" : "Take the 2nd \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eAvenue of the Americas\u003c/b\u003e",
212
+ "polyline" : {
213
+ "points" : "artwF~urbMeCaByBwA}ByA{B{AwBwA}ByA{ByA{ByA{B{AuByAQMuBuAgC}A{BwA{BwA{BwA}ByAwB_B}BwAIIeBeAUOeCcB}B{A{B{A"
214
+ },
215
+ "start_location" : {
216
+ "lat" : 40.7428904,
217
+ "lng" : -73.99280299999999
218
+ },
219
+ "travel_mode" : "DRIVING"
220
+ },
221
+ {
222
+ "distance" : {
223
+ "text" : "0.3 mi",
224
+ "value" : 547
225
+ },
226
+ "duration" : {
227
+ "text" : "2 mins",
228
+ "value" : 109
229
+ },
230
+ "end_location" : {
231
+ "lat" : 40.7591625,
232
+ "lng" : -73.988378
233
+ },
234
+ "html_instructions" : "Turn \u003cb\u003eleft\u003c/b\u003e onto \u003cb\u003eW 45th St\u003c/b\u003e",
235
+ "maneuver" : "turn-left",
236
+ "polyline" : {
237
+ "points" : "yhwwFzvpbMkFrPITGRi@`Bg@`B_B`Fm@jB"
238
+ },
239
+ "start_location" : {
240
+ "lat" : 40.7567653,
241
+ "lng" : -73.98270230000001
242
+ },
243
+ "travel_mode" : "DRIVING"
244
+ },
245
+ {
246
+ "distance" : {
247
+ "text" : "0.5 mi",
248
+ "value" : 875
249
+ },
250
+ "duration" : {
251
+ "text" : "2 mins",
252
+ "value" : 97
253
+ },
254
+ "end_location" : {
255
+ "lat" : 40.7660501,
256
+ "lng" : -73.9833663
257
+ },
258
+ "html_instructions" : "Turn \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003e8th Ave\u003c/b\u003e",
259
+ "maneuver" : "turn-right",
260
+ "polyline" : {
261
+ "points" : "wwwwFjzqbM}ByA{B}A}BwA{B{A}ByA}B{A{B{A}ByA}ByA{B}A}ByA"
262
+ },
263
+ "start_location" : {
264
+ "lat" : 40.7591625,
265
+ "lng" : -73.988378
266
+ },
267
+ "travel_mode" : "DRIVING"
268
+ },
269
+ {
270
+ "distance" : {
271
+ "text" : "0.3 mi",
272
+ "value" : 546
273
+ },
274
+ "duration" : {
275
+ "text" : "3 mins",
276
+ "value" : 160
277
+ },
278
+ "end_location" : {
279
+ "lat" : 40.7636538,
280
+ "lng" : -73.9777149
281
+ },
282
+ "html_instructions" : "Turn \u003cb\u003eright\u003c/b\u003e onto \u003cb\u003eW 56th St\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003eDestination will be on the right\u003c/div\u003e",
283
+ "maneuver" : "turn-right",
284
+ "polyline" : {
285
+ "points" : "ybywF`{pbMnBkG\\_A`BiFxAwEtC}I"
286
+ },
287
+ "start_location" : {
288
+ "lat" : 40.7660501,
289
+ "lng" : -73.9833663
290
+ },
291
+ "travel_mode" : "DRIVING"
292
+ }
293
+ ],
294
+ "via_waypoint" : []
295
+ }
296
+ ],
297
+ "overview_polyline" : {
298
+ "points" : "{quwFndqbMfD|BtFnDnJnGdIhFd@ZxAbAr@d@sDhLyAvEeCaB|FsQDGLAl@H^Lr@d@sDhLyAvEeCaBwFqDmNgJwFuDgCgBuNcJyFqDwB_B}BwAoBoA{CsByFwDuFhQyDxLm@jB}ByAyFuDsNmJ{FsDyFwDlCkIzDaMtC}I"
299
+ },
300
+ "summary" : "Avenue of the Americas",
301
+ "warnings" : [],
302
+ "waypoint_order" : [ 0 ]
303
+ }
304
+ ],
305
+ "status" : "OK"
306
+ }
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/json_response"
3
+
4
+ describe GoogleMapsAPI::Directions::Response do
5
+ include_context "json response"
6
+
7
+ subject { GoogleMapsAPI::Directions::Response }
8
+
9
+ describe ".from_json" do
10
+ it "returns a new response" do
11
+ expect(subject.from_json(json)).to be_a(subject)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/json_response"
3
+
4
+ describe GoogleMapsAPI::Directions::Route do
5
+ include_context "json response"
6
+
7
+ subject { GoogleMapsAPI::Directions::Route }
8
+
9
+ describe ".from_hash" do
10
+ it "returns a new route" do
11
+ expect(subject.from_hash(parsed_json["routes"].first)).to be_a(subject)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/json_response"
3
+
4
+ describe GoogleMapsAPI::Directions::Step do
5
+ include_context "json response"
6
+
7
+ subject { GoogleMapsAPI::Directions::Step }
8
+
9
+ describe ".from_hash" do
10
+ it "returns a new step" do
11
+ hash = parsed_json["routes"].first["legs"].first["steps"].first
12
+ expect(subject.from_hash(hash)).to be_a(subject)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+ require "google_maps_api/directions/request_lets"
3
+
4
+ describe GoogleMapsAPI::Directions do
5
+ subject { GoogleMapsAPI::Directions }
6
+
7
+ include_context "request lets"
8
+
9
+ describe ".route" do
10
+ it "performs a request" do
11
+ expect_any_instance_of(subject::Request).to receive(:perform).with(no_args)
12
+ subject.route(origin, destination, options)
13
+ end
14
+
15
+ it "returns a response" do
16
+ expect(subject.route(origin, destination, options)).to be_a(subject::Response)
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,84 @@
1
+ require "google_maps_api/directions"
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
6
+ # file to always be loaded, without a need to explicitly require it in any files.
7
+ #
8
+ # Given that it is always loaded, you are encouraged to keep this file as
9
+ # light-weight as possible. Requiring heavyweight dependencies from this file
10
+ # (such as loading up an entire rails app) will add to the boot time of your
11
+ # test suite on EVERY test run, even for an individual file that may not need
12
+ # all of that loaded.
13
+ #
14
+ # The `.rspec` file also contains a few flags that are not defaults but that
15
+ # users commonly want.
16
+ #
17
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
18
+ RSpec.configure do |config|
19
+ # The settings below are suggested to provide a good initial experience
20
+ # with RSpec, but feel free to customize to your heart's content.
21
+ =begin
22
+ # These two settings work together to allow you to limit a spec run
23
+ # to individual examples or groups you care about by tagging them with
24
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
25
+ # get run.
26
+ config.filter_run :focus
27
+ config.run_all_when_everything_filtered = true
28
+
29
+ # Many RSpec users commonly either run the entire suite or an individual
30
+ # file, and it's useful to allow more verbose output when running an
31
+ # individual spec file.
32
+ if config.files_to_run.one?
33
+ # RSpec filters the backtrace by default so as not to be so noisy.
34
+ # This causes the full backtrace to be printed when running a single
35
+ # spec file (e.g. to troubleshoot a particular spec failure).
36
+ config.full_backtrace = true
37
+
38
+ # Use the documentation formatter for detailed output,
39
+ # unless a formatter has already been configured
40
+ # (e.g. via a command-line flag).
41
+ config.formatter = 'doc' if config.formatters.none?
42
+ end
43
+
44
+ # Print the 10 slowest examples and example groups at the
45
+ # end of the spec run, to help surface which specs are running
46
+ # particularly slow.
47
+ config.profile_examples = 10
48
+
49
+ # Run specs in random order to surface order dependencies. If you find an
50
+ # order dependency and want to debug it, you can fix the order by providing
51
+ # the seed, which is printed after each run.
52
+ # --seed 1234
53
+ config.order = :random
54
+
55
+ # Seed global randomization in this process using the `--seed` CLI option.
56
+ # Setting this allows you to use `--seed` to deterministically reproduce
57
+ # test failures related to randomization by passing the same `--seed` value
58
+ # as the one that triggered the failure.
59
+ Kernel.srand config.seed
60
+
61
+ # rspec-expectations config goes here. You can use an alternate
62
+ # assertion/expectation library such as wrong or the stdlib/minitest
63
+ # assertions if you prefer.
64
+ config.expect_with :rspec do |expectations|
65
+ # Enable only the newer, non-monkey-patching expect syntax.
66
+ # For more details, see:
67
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
68
+ expectations.syntax = :expect
69
+ end
70
+
71
+ # rspec-mocks config goes here. You can use an alternate test double
72
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
73
+ config.mock_with :rspec do |mocks|
74
+ # Enable only the newer, non-monkey-patching expect syntax.
75
+ # For more details, see:
76
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
77
+ mocks.syntax = :expect
78
+
79
+ # Prevents you from mocking or stubbing a method that does not exist on
80
+ # a real object. This is generally recommended.
81
+ mocks.verify_partial_doubles = true
82
+ end
83
+ =end
84
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_maps_api-directions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Felipe Zavan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0.beta2
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '4'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 3.0.0.beta2
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '4'
61
+ - !ruby/object:Gem::Dependency
62
+ name: google_maps_api-core
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description:
76
+ email:
77
+ - zavan@outlook.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - ".rspec"
84
+ - Gemfile
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - google_maps_api-directions.gemspec
89
+ - lib/google_maps_api/directions.rb
90
+ - lib/google_maps_api/directions/bounds.rb
91
+ - lib/google_maps_api/directions/encoded_polyline.rb
92
+ - lib/google_maps_api/directions/exceptions.rb
93
+ - lib/google_maps_api/directions/leg.rb
94
+ - lib/google_maps_api/directions/leg_and_step_common_builders.rb
95
+ - lib/google_maps_api/directions/request.rb
96
+ - lib/google_maps_api/directions/response.rb
97
+ - lib/google_maps_api/directions/route.rb
98
+ - lib/google_maps_api/directions/step.rb
99
+ - lib/google_maps_api/directions/version.rb
100
+ - spec/google_maps_api/directions/bounds_spec.rb
101
+ - spec/google_maps_api/directions/json_response.rb
102
+ - spec/google_maps_api/directions/leg_spec.rb
103
+ - spec/google_maps_api/directions/request_lets.rb
104
+ - spec/google_maps_api/directions/request_spec.rb
105
+ - spec/google_maps_api/directions/response_mock.json
106
+ - spec/google_maps_api/directions/response_spec.rb
107
+ - spec/google_maps_api/directions/route_spec.rb
108
+ - spec/google_maps_api/directions/step_spec.rb
109
+ - spec/google_maps_api/directions_spec.rb
110
+ - spec/spec_helper.rb
111
+ homepage: https://github.com/zavan/google_maps_api-directions
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.2.2
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Wrapper around the Google Maps Directions API.
135
+ test_files:
136
+ - spec/google_maps_api/directions/bounds_spec.rb
137
+ - spec/google_maps_api/directions/json_response.rb
138
+ - spec/google_maps_api/directions/leg_spec.rb
139
+ - spec/google_maps_api/directions/request_lets.rb
140
+ - spec/google_maps_api/directions/request_spec.rb
141
+ - spec/google_maps_api/directions/response_mock.json
142
+ - spec/google_maps_api/directions/response_spec.rb
143
+ - spec/google_maps_api/directions/route_spec.rb
144
+ - spec/google_maps_api/directions/step_spec.rb
145
+ - spec/google_maps_api/directions_spec.rb
146
+ - spec/spec_helper.rb