google_maps_api-directions 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.
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