routing 0.0.4 → 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 +4 -4
- data/lib/routing.rb +11 -3
- data/lib/routing/adapter.rb +1 -0
- data/lib/routing/adapter/here.rb +12 -40
- data/lib/routing/adapter/navteq.rb +8 -42
- data/lib/routing/adapter/rest_adapter.rb +60 -0
- data/lib/routing/parser/here_simple.rb +2 -2
- data/lib/routing/parser/navteq_simple.rb +3 -3
- data/lib/routing/version.rb +1 -1
- data/routing.gemspec +4 -2
- data/spec/routing/adapter/here_spec.rb +46 -26
- data/spec/routing/adapter/navteq_spec.rb +45 -37
- data/spec/routing/adapter/test_spec.rb +7 -13
- data/spec/routing/geo_point_spec.rb +9 -2
- data/spec/routing/parser/here_simple_spec.rb +9 -10
- data/spec/routing/parser/navteq_simple_spec.rb +10 -11
- data/spec/routing_spec.rb +16 -28
- metadata +34 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a49e29dbffb57a00e02111ebb486d6ef57c48d9
|
4
|
+
data.tar.gz: 0a4104acf4545f919bee3a4c7b22cdc8eb14076b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10aa9dc049fe739036ce6149ec156735179a51bb8a33cb72ea2902d5a55d530402e40e35011801bfd631e104690b1022a3c1a9ca28fbda23199e82f5b32b331d
|
7
|
+
data.tar.gz: 98ebd1ea41a04d78d9aa8712fd2503bead5fd27640387a5fd54640e5d68d016d188906d4b74e7e278f153f9de0cfe5e6c7ef1ad03800a0e2f60e90584e456424
|
data/lib/routing.rb
CHANGED
@@ -16,16 +16,16 @@ class Routing
|
|
16
16
|
attr_writer :default_adapter
|
17
17
|
|
18
18
|
# The default adapter/routing service that is used, if no one is specified.
|
19
|
-
# Currently this is {Routing::Adapter::
|
19
|
+
# Currently this is {Routing::Adapter::Here}.
|
20
20
|
#
|
21
21
|
# @return [Object] Current default adapter.
|
22
22
|
def default_adapter
|
23
|
-
@default_adapter ||= Routing::Adapter::
|
23
|
+
@default_adapter ||= Routing::Adapter::Here.new
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
attr_reader :adapter
|
29
29
|
|
30
30
|
# Creates a new instance of the routing class
|
31
31
|
#
|
@@ -37,6 +37,14 @@ class Routing
|
|
37
37
|
yield(self) if block_given?
|
38
38
|
end
|
39
39
|
|
40
|
+
# Returns a copy of the current middleware stack.
|
41
|
+
#
|
42
|
+
# @return [Array<Routing::Middleware>]
|
43
|
+
# An array of all registered middlewares.
|
44
|
+
def middlewares
|
45
|
+
@middlewares.dup
|
46
|
+
end
|
47
|
+
|
40
48
|
# Calculates a route for the passed {GeoPoint}s.
|
41
49
|
# These will be passed through the middleware stack and will
|
42
50
|
# finally be given to the configured adapter which calculates a route out of it.
|
data/lib/routing/adapter.rb
CHANGED
data/lib/routing/adapter/here.rb
CHANGED
@@ -1,39 +1,15 @@
|
|
1
1
|
require 'time'
|
2
|
-
require 'faraday'
|
3
2
|
|
4
3
|
class Routing
|
5
4
|
module Adapter
|
6
|
-
|
7
5
|
# Adapter for a Nokia Here Routing Service v7 server.
|
8
6
|
# It passes the {GeoPoint}s to the routing service and will return another
|
9
7
|
# Array of {GeoPoint}s, representing the calculated route.
|
10
|
-
class Here
|
11
|
-
|
12
|
-
def initialize(options = {})
|
13
|
-
@options = {
|
14
|
-
:host => 'http://route.api.here.com',
|
15
|
-
:service_path => '/routing/7.2/calculateroute.json',
|
16
|
-
:parser => ::Routing::Parser::HereSimple
|
17
|
-
}.merge(options)
|
18
|
-
end
|
19
|
-
|
20
|
-
def calculate(geo_points)
|
21
|
-
response = connection.get do |request|
|
22
|
-
request.url(options[:service_path])
|
23
|
-
request.params = default_params.merge(geo_points_to_params(geo_points)).merge(options[:credentials])
|
24
|
-
end
|
25
|
-
|
26
|
-
parse(response.body)
|
27
|
-
end
|
8
|
+
class Here < RestAdapter
|
9
|
+
property :credentials, accepts: Hash
|
28
10
|
|
29
|
-
|
30
|
-
|
31
|
-
def parse(response)
|
32
|
-
options[:parser].new(response).to_geo_points
|
33
|
-
end
|
34
|
-
|
35
|
-
def default_params
|
36
|
-
options[:default_params] || {
|
11
|
+
def self.default_params
|
12
|
+
{
|
37
13
|
departure: Time.now.utc.iso8601,
|
38
14
|
mode: "fastest;car",
|
39
15
|
language: "de_DE",
|
@@ -42,21 +18,17 @@ class Routing
|
|
42
18
|
}
|
43
19
|
end
|
44
20
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
@connection ||= Faraday.new(:url => options[:host]) do |builder|
|
51
|
-
builder.request :url_encoded
|
52
|
-
builder.adapter :net_http
|
53
|
-
end
|
21
|
+
def initialize(attrs = {})
|
22
|
+
attrs[:host] ||= 'route.api.here.com'
|
23
|
+
attrs[:path] ||= '/routing/7.2/calculateroute.json'
|
24
|
+
attrs[:parser] ||= ::Routing::Parser::HereSimple
|
25
|
+
super(attrs)
|
54
26
|
end
|
55
27
|
|
56
|
-
def
|
57
|
-
|
28
|
+
def calculate(geo_points)
|
29
|
+
response = request(params.merge(convert_geo_points_to_params(geo_points)).merge(credentials))
|
30
|
+
parse(response.body)
|
58
31
|
end
|
59
|
-
|
60
32
|
end
|
61
33
|
end
|
62
34
|
end
|
@@ -1,37 +1,13 @@
|
|
1
1
|
require 'time'
|
2
|
-
require 'faraday'
|
3
2
|
|
4
3
|
class Routing
|
5
4
|
module Adapter
|
6
|
-
|
7
5
|
# Adapter for a NAVTEQ LBSP Routing Service v6 server.
|
8
6
|
# It passes the {GeoPoint}s to the routing service and will return another
|
9
7
|
# Array of {GeoPoint}s, representing the calculated route.
|
10
|
-
class Navteq
|
11
|
-
|
12
|
-
|
13
|
-
@options = {
|
14
|
-
:service_path => '/routing/6.2/calculateroute.json',
|
15
|
-
:parser => ::Routing::Parser::NavteqSimple
|
16
|
-
}.merge(options)
|
17
|
-
end
|
18
|
-
|
19
|
-
def calculate(geo_points)
|
20
|
-
response = connection.get do |request|
|
21
|
-
request.url(options[:service_path])
|
22
|
-
request.params = default_params.merge(geo_points_to_params(geo_points))
|
23
|
-
end
|
24
|
-
parse(response.body)
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def parse(response)
|
30
|
-
options[:parser].new(response).to_geo_points
|
31
|
-
end
|
32
|
-
|
33
|
-
def default_params
|
34
|
-
options[:default_params] || {
|
8
|
+
class Navteq < RestAdapter
|
9
|
+
def self.default_params
|
10
|
+
{
|
35
11
|
departure: Time.now.utc.iso8601,
|
36
12
|
mode0: "fastest;car",
|
37
13
|
language: "de_DE",
|
@@ -40,21 +16,11 @@ class Routing
|
|
40
16
|
}
|
41
17
|
end
|
42
18
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def connection
|
48
|
-
@connection ||= Faraday.new(:url => options[:host]) do |builder|
|
49
|
-
builder.request :url_encoded
|
50
|
-
builder.adapter :net_http
|
51
|
-
end
|
19
|
+
def initialize(attrs = {})
|
20
|
+
attrs[:path] ||= '/routing/6.2/calculateroute.json'
|
21
|
+
attrs[:parser] ||= ::Routing::Parser::NavteqSimple
|
22
|
+
super(attrs)
|
52
23
|
end
|
53
|
-
|
54
|
-
def options
|
55
|
-
@options || {}
|
56
|
-
end
|
57
|
-
|
58
24
|
end
|
59
25
|
end
|
60
|
-
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'faraday'
|
3
|
+
require 'smart_properties'
|
4
|
+
|
5
|
+
class Routing
|
6
|
+
module Adapter
|
7
|
+
class RestAdapter
|
8
|
+
include SmartProperties
|
9
|
+
|
10
|
+
property :scheme, converts: :to_str, accepts: ['http', 'https'], default: 'http', required: true
|
11
|
+
property :host, converts: :to_str, required: true
|
12
|
+
property :path, converts: :to_str, required: true
|
13
|
+
property :parser, accepts: Class
|
14
|
+
property :params, accepts: Hash
|
15
|
+
|
16
|
+
def self.default_params
|
17
|
+
{}
|
18
|
+
end
|
19
|
+
|
20
|
+
def calculate(geo_points)
|
21
|
+
response = request(params.merge(convert_geo_points_to_params(geo_points)))
|
22
|
+
parse(response.body)
|
23
|
+
end
|
24
|
+
|
25
|
+
def params
|
26
|
+
super || self.class.default_params
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def base_url
|
32
|
+
"%s://%s" % [scheme, host]
|
33
|
+
end
|
34
|
+
|
35
|
+
def request(params = nil)
|
36
|
+
connection.get do |request|
|
37
|
+
request.url(path)
|
38
|
+
request.params = params if params
|
39
|
+
yield request if block_given?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def connection
|
44
|
+
@connection ||= Faraday.new(url: base_url) do |builder|
|
45
|
+
builder.request :url_encoded
|
46
|
+
builder.adapter :net_http
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse(response)
|
51
|
+
parser.new(response).to_geo_points
|
52
|
+
end
|
53
|
+
|
54
|
+
def convert_geo_points_to_params(geo_points)
|
55
|
+
Hash[geo_points.each_with_index.map { |point, i| [ "waypoint#{i}", "geo!#{point.lat},#{point.lng}" ] }]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -46,7 +46,7 @@ class Routing
|
|
46
46
|
# For the last leg we parse the last maneuver right at the end
|
47
47
|
maneuvers = leg["maneuver"][0...-1]
|
48
48
|
maneuvers.map do |maneuver|
|
49
|
-
parse_maneuver(maneuver, :
|
49
|
+
parse_maneuver(maneuver, waypoint: (maneuver == maneuvers.first))
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -89,7 +89,7 @@ class Routing
|
|
89
89
|
# @raise [NoMatchingMappedPositionFound] If no matching original position is found.
|
90
90
|
def search_original_position(geo_point)
|
91
91
|
matching_waypoint = @route["waypoint"].detect do |waypoint|
|
92
|
-
waypoint["mappedPosition"]["latitude"] == geo_point.lat &&
|
92
|
+
waypoint["mappedPosition"]["latitude"] == geo_point.lat &&
|
93
93
|
waypoint["mappedPosition"]["longitude"] == geo_point.lng
|
94
94
|
end or raise NoMatchingMappedPositionFound
|
95
95
|
|
@@ -46,7 +46,7 @@ class Routing
|
|
46
46
|
# For the last leg we parse the last maneuver right at the end
|
47
47
|
maneuvers = leg["Maneuver"][0...-1]
|
48
48
|
maneuvers.map do |maneuver|
|
49
|
-
parse_maneuver(maneuver, :
|
49
|
+
parse_maneuver(maneuver, waypoint: (maneuver == maneuvers.first))
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -89,7 +89,7 @@ class Routing
|
|
89
89
|
# @raise [NoMatchingMappedPositionFound] If no matching original position is found.
|
90
90
|
def search_original_position(geo_point)
|
91
91
|
matching_waypoint = @route["Waypoint"].detect do |waypoint|
|
92
|
-
waypoint["MappedPosition"]["Latitude"] == geo_point.lat &&
|
92
|
+
waypoint["MappedPosition"]["Latitude"] == geo_point.lat &&
|
93
93
|
waypoint["MappedPosition"]["Longitude"] == geo_point.lng
|
94
94
|
end or raise NoMatchingMappedPositionFound
|
95
95
|
|
@@ -107,4 +107,4 @@ class Routing
|
|
107
107
|
|
108
108
|
end
|
109
109
|
end
|
110
|
-
end
|
110
|
+
end
|
data/lib/routing/version.rb
CHANGED
data/routing.gemspec
CHANGED
@@ -13,7 +13,9 @@ Gem::Specification.new do |gem|
|
|
13
13
|
|
14
14
|
gem.add_dependency "faraday", ">= 0.7.0"
|
15
15
|
gem.add_dependency "json"
|
16
|
-
gem.
|
16
|
+
gem.add_dependency "smart_properties", "~> 1.0"
|
17
|
+
gem.add_development_dependency "rspec", ">= 2.11"
|
18
|
+
gem.add_development_dependency "rake"
|
17
19
|
|
18
20
|
gem.files = `git ls-files`.split($\)
|
19
21
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -21,4 +23,4 @@ Gem::Specification.new do |gem|
|
|
21
23
|
gem.name = "routing"
|
22
24
|
gem.require_paths = ["lib"]
|
23
25
|
gem.version = Routing::VERSION
|
24
|
-
end
|
26
|
+
end
|
@@ -2,23 +2,27 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Routing::Adapter::Here do
|
4
4
|
|
5
|
-
let(:response) {
|
6
|
-
let(:request) {
|
7
|
-
let(:connection) {
|
8
|
-
let(:parser_class)
|
9
|
-
|
10
|
-
|
5
|
+
let(:response) { double(:response).as_null_object }
|
6
|
+
let(:request) { double(:request).as_null_object }
|
7
|
+
let(:connection) { double(:connection).as_null_object }
|
8
|
+
let(:parser_class) do
|
9
|
+
Class.new.tap do |klass|
|
10
|
+
klass.stub(:new => parser)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
let(:parser) { double(:parser).as_null_object }
|
14
|
+
let(:credentials) { {:app_id => "123", :app_code => "456"} }
|
11
15
|
let(:options) do
|
12
|
-
{ :parser => parser_class, :credentials =>
|
16
|
+
{ :parser => parser_class, :credentials => credentials}
|
13
17
|
end
|
14
18
|
|
15
|
-
let(:geo_points) { [
|
19
|
+
let(:geo_points) { [double(:lat => 1, :lng => 2), double(:lat => 3, :lng => 4), double(:lat => 5, :lng => 6)] }
|
16
20
|
|
17
|
-
subject { described_class.new(options) }
|
21
|
+
subject(:adapter) { described_class.new(options) }
|
18
22
|
|
19
23
|
before do
|
20
|
-
connection.
|
21
|
-
Faraday.
|
24
|
+
allow(connection).to receive(:get).and_yield(request).and_return(response)
|
25
|
+
allow(Faraday).to receive(:new).and_return(connection)
|
22
26
|
end
|
23
27
|
|
24
28
|
context 'creating a new instance' do
|
@@ -27,37 +31,51 @@ describe Routing::Adapter::Here do
|
|
27
31
|
end
|
28
32
|
|
29
33
|
it 'allows setting the host' do
|
30
|
-
Faraday.
|
31
|
-
|
34
|
+
expect(Faraday).to receive(:new).with(:url => 'http://other.com')
|
35
|
+
|
36
|
+
adapter = described_class.new(options.merge!(:host => 'other.com'))
|
37
|
+
adapter.calculate(geo_points)
|
32
38
|
end
|
33
39
|
|
34
40
|
it 'allows setting the default params' do
|
35
41
|
params = { :hello => "world" }
|
36
|
-
|
37
|
-
|
42
|
+
expect(request).to receive(:params=).with(hash_including(params))
|
43
|
+
|
44
|
+
adapter = described_class.new(options.merge(:params => params))
|
45
|
+
adapter.calculate(geo_points)
|
38
46
|
end
|
39
47
|
|
40
48
|
it 'sets the api credentials' do
|
41
|
-
request.
|
49
|
+
expect(request).to receive(:params=).with(hash_including({ :app_id => "123", :app_code => "456" }))
|
50
|
+
adapter.calculate(geo_points)
|
42
51
|
end
|
43
52
|
|
44
53
|
it 'should allow setting the service path' do
|
45
|
-
|
46
|
-
|
54
|
+
expect(request).to receive(:url).with('/some/path.json')
|
55
|
+
|
56
|
+
adapter = described_class.new(options.merge(:path => '/some/path.json'))
|
57
|
+
adapter.calculate(geo_points)
|
47
58
|
end
|
48
59
|
|
49
60
|
it 'should use a default service path when none is given' do
|
50
|
-
request.
|
61
|
+
expect(request).to receive(:url).with('/routing/7.2/calculateroute.json')
|
62
|
+
|
63
|
+
adapter = described_class.new(options)
|
64
|
+
adapter.calculate(geo_points)
|
51
65
|
end
|
52
66
|
|
53
67
|
it 'should allow setting the parser' do
|
54
|
-
|
55
|
-
|
68
|
+
expect(parser_class).to receive(:new)
|
69
|
+
|
70
|
+
adapter = described_class.new(options.merge(:parser => parser_class))
|
71
|
+
adapter.calculate(geo_points)
|
56
72
|
end
|
57
73
|
|
58
74
|
it 'should use a default parser when none is given' do
|
59
|
-
|
60
|
-
|
75
|
+
expect(Routing::Parser::HereSimple).to receive(:new).and_return(parser)
|
76
|
+
|
77
|
+
adapter = described_class.new(credentials: credentials)
|
78
|
+
adapter.calculate(geo_points)
|
61
79
|
end
|
62
80
|
|
63
81
|
it 'ignores unknown options' do
|
@@ -68,21 +86,23 @@ describe Routing::Adapter::Here do
|
|
68
86
|
describe '#calculate' do
|
69
87
|
it 'passes the response to the parser' do
|
70
88
|
response.stub(:body => '...')
|
71
|
-
parser_class.
|
89
|
+
expect(parser_class).to receive(:new).with('...')
|
90
|
+
adapter.calculate(geo_points)
|
72
91
|
end
|
73
92
|
|
74
93
|
it 'should return the parser\'s result' do
|
75
94
|
result = [double, double, double]
|
76
95
|
parser.stub(:to_geo_points => result)
|
77
|
-
|
96
|
+
expect(adapter.calculate(geo_points)).to be(result)
|
78
97
|
end
|
79
98
|
|
80
99
|
it 'should convert the geo points into a compatible format' do
|
81
|
-
request.
|
100
|
+
expect(request).to receive(:params=).with hash_including({
|
82
101
|
'waypoint0' => 'geo!1,2',
|
83
102
|
'waypoint1' => 'geo!3,4',
|
84
103
|
'waypoint2' => 'geo!5,6'
|
85
104
|
})
|
105
|
+
adapter.calculate(geo_points)
|
86
106
|
end
|
87
107
|
end
|
88
108
|
end
|
@@ -1,85 +1,93 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Routing::Adapter::Navteq do
|
4
|
+
let(:response) { double(:response).as_null_object }
|
5
|
+
let(:request) { double(:request).as_null_object }
|
6
|
+
let(:connection) { double(:connection).as_null_object }
|
7
|
+
let(:parser_class) do
|
8
|
+
Class.new.tap do |klass|
|
9
|
+
klass.stub(new: parser)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let(:parser) { double(:parser).as_null_object }
|
13
|
+
let(:options) { { host: 'example.com', parser: parser_class } }
|
14
|
+
let(:geo_points) { [double(lat: 1, lng: 2), double(lat: 3, lng: 4), double(lat: 5, lng: 6)] }
|
4
15
|
|
5
|
-
|
6
|
-
let(:request) { mock(:request).as_null_object }
|
7
|
-
let(:connection) { mock(:connection).as_null_object }
|
8
|
-
let(:parser_class) { mock(:parser_class, :new => parser) }
|
9
|
-
let(:parser) { mock(:parser).as_null_object }
|
10
|
-
|
11
|
-
let(:options) { { :host => 'http://example.com', :parser => parser_class } }
|
12
|
-
|
13
|
-
let(:geo_points) { [stub(:lat => 1, :lng => 2), stub(:lat => 3, :lng => 4), stub(:lat => 5, :lng => 6)] }
|
14
|
-
|
15
|
-
|
16
|
-
subject { described_class.new(options) }
|
16
|
+
subject(:adapter) { described_class.new(options) }
|
17
17
|
|
18
18
|
before do
|
19
|
-
connection.
|
20
|
-
Faraday.
|
19
|
+
allow(connection).to receive(:get).and_yield(request).and_return(response)
|
20
|
+
allow(Faraday).to receive(:new).and_return(connection)
|
21
21
|
end
|
22
22
|
|
23
23
|
after { subject.calculate(geo_points) }
|
24
24
|
|
25
25
|
context 'creating a new instance' do
|
26
|
-
it 'can be instantiated without arguments' do
|
27
|
-
expect { described_class.new }.to_not raise_error
|
28
|
-
end
|
29
|
-
|
30
26
|
it 'allows setting the host' do
|
31
|
-
Faraday.
|
32
|
-
|
27
|
+
expect(Faraday).to receive(:new).with(url: 'http://other.com')
|
28
|
+
|
29
|
+
adapter = described_class.new(options.merge(host: 'other.com'))
|
30
|
+
adapter.calculate(geo_points)
|
33
31
|
end
|
34
32
|
|
35
33
|
it 'allows setting the default params' do
|
36
|
-
params = {
|
37
|
-
|
38
|
-
|
34
|
+
params = {hello: "world"}
|
35
|
+
expect(request).to receive(:params=).with(hash_including(params))
|
36
|
+
|
37
|
+
adapter = described_class.new(options.merge(params: params))
|
38
|
+
adapter.calculate(geo_points)
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should allow setting the service path' do
|
42
|
-
|
43
|
-
|
42
|
+
expect(request).to receive(:url).with('/some/path.json')
|
43
|
+
|
44
|
+
adapter = described_class.new(options.merge(path: '/some/path.json'))
|
45
|
+
adapter.calculate(geo_points)
|
44
46
|
end
|
45
47
|
|
46
48
|
it 'should use a default service path when none is given' do
|
47
|
-
request.
|
49
|
+
expect(request).to receive(:url).with('/routing/6.2/calculateroute.json')
|
50
|
+
adapter.calculate(geo_points)
|
48
51
|
end
|
49
52
|
|
50
53
|
it 'should allow setting the parser' do
|
51
|
-
|
52
|
-
|
54
|
+
expect(parser_class).to receive(:new)
|
55
|
+
|
56
|
+
adapter = described_class.new(options.merge(parser: parser_class))
|
57
|
+
adapter.calculate(geo_points)
|
53
58
|
end
|
54
59
|
|
55
60
|
it 'should use a default parser when none is given' do
|
56
|
-
|
57
|
-
|
61
|
+
expect(Routing::Parser::NavteqSimple).to receive(:new).and_return(parser)
|
62
|
+
|
63
|
+
adapter = described_class.new(host: 'example.com')
|
64
|
+
adapter.calculate(geo_points)
|
58
65
|
end
|
59
66
|
|
60
67
|
it 'ignores unknown options' do
|
61
|
-
expect { described_class.new(:
|
68
|
+
expect { described_class.new(options.merge(hello: "world")) }.to_not raise_error
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
65
72
|
describe '#calculate' do
|
66
73
|
it 'passes the response body to the parser' do
|
67
|
-
response.stub(:
|
68
|
-
parser_class.
|
74
|
+
response.stub(body: '...')
|
75
|
+
expect(parser_class).to receive(:new).with('...')
|
76
|
+
adapter.calculate(geo_points)
|
69
77
|
end
|
70
78
|
|
71
79
|
it 'should return the parser\'s result' do
|
72
80
|
result = [double, double, double]
|
73
|
-
parser.stub(:
|
74
|
-
subject.calculate(geo_points).
|
81
|
+
parser.stub(to_geo_points: result)
|
82
|
+
expect(subject.calculate(geo_points)).to be(result)
|
75
83
|
end
|
76
84
|
|
77
85
|
it 'should convert the geo points into a compatible format' do
|
78
|
-
request.
|
86
|
+
expect(request).to receive(:params=).with hash_including({
|
79
87
|
'waypoint0' => 'geo!1,2',
|
80
88
|
'waypoint1' => 'geo!3,4',
|
81
89
|
'waypoint2' => 'geo!5,6'
|
82
90
|
})
|
83
91
|
end
|
84
92
|
end
|
85
|
-
end
|
93
|
+
end
|
@@ -1,29 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Routing::Adapter::Test do
|
4
|
-
|
5
4
|
context 'creating a new instance' do
|
6
|
-
|
7
5
|
it 'can be instantiated without arguments' do
|
8
6
|
expect { Routing::Adapter::Test.new }.to_not raise_error
|
9
7
|
end
|
10
|
-
|
11
8
|
end
|
12
9
|
|
13
10
|
describe '#calculate' do
|
14
|
-
|
15
|
-
let(:geo_points) { [stub(:lat => 1, :lng => 2), stub(:lat => 3, :lng => 4), stub(:lat => 5, :lng => 6)] }
|
11
|
+
let(:geo_points) { [double(lat: 1, lng: 2), double(lat: 3, lng: 4), double(lat: 5, lng: 6)] }
|
16
12
|
|
17
13
|
it 'returns an array of geopoints with values that are passed to the method' do
|
18
14
|
subject.calculate(geo_points).each_with_index do |new_geo_point, index|
|
19
|
-
new_geo_point.lat.
|
20
|
-
new_geo_point.lng.
|
21
|
-
new_geo_point.original_lng.
|
22
|
-
new_geo_point.original_lng.
|
23
|
-
new_geo_point.
|
15
|
+
expect(new_geo_point.lat).to eql(geo_points[index].lat)
|
16
|
+
expect(new_geo_point.lng).to eql(geo_points[index].lng)
|
17
|
+
expect(new_geo_point.original_lng).to eql(geo_points[index].lng)
|
18
|
+
expect(new_geo_point.original_lng).to eql(geo_points[index].lng)
|
19
|
+
expect(new_geo_point).to be_waypoint
|
24
20
|
end
|
25
21
|
end
|
26
|
-
|
27
22
|
end
|
28
|
-
|
29
|
-
end
|
23
|
+
end
|
@@ -10,8 +10,15 @@ describe Routing::GeoPoint do
|
|
10
10
|
context 'initialized with attributes' do
|
11
11
|
subject { described_class.new(:lat => 1, :lng => 2) }
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
describe '#lat' do
|
14
|
+
subject { super().lat }
|
15
|
+
it { should be(1) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#lng' do
|
19
|
+
subject { super().lng }
|
20
|
+
it { should be(2) }
|
21
|
+
end
|
15
22
|
|
16
23
|
it 'ignores passed attributes that dont exist' do
|
17
24
|
expect { described_class.new(:hello => :world) }.to_not raise_error
|
@@ -2,12 +2,11 @@ require 'spec_helper'
|
|
2
2
|
require 'json'
|
3
3
|
|
4
4
|
describe Routing::Parser::HereSimple do
|
5
|
-
|
6
5
|
context 'with a error response' do
|
7
6
|
let(:error_response) { fixture('here/error_response.json') }
|
8
7
|
|
9
8
|
it 'should throw an RoutingFailed error' do
|
10
|
-
|
9
|
+
expect{ described_class.new(error_response) }.to raise_error(Routing::Parser::RoutingFailed)
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
@@ -16,7 +15,7 @@ describe Routing::Parser::HereSimple do
|
|
16
15
|
let(:json_response) { JSON.parse(response) }
|
17
16
|
let(:original_geo_points) do
|
18
17
|
json_response['response']['route'].first['waypoint'].collect do |waypoint|
|
19
|
-
|
18
|
+
double({
|
20
19
|
lat: waypoint['originalPosition']['latitude'],
|
21
20
|
lng: waypoint['originalPosition']['longitude']
|
22
21
|
})
|
@@ -27,7 +26,7 @@ describe Routing::Parser::HereSimple do
|
|
27
26
|
subject { described_class.new(response).to_geo_points }
|
28
27
|
|
29
28
|
it 'returns geopoints' do
|
30
|
-
subject.each { |point| point.
|
29
|
+
subject.each { |point| expect(point).to be_a(::Routing::GeoPoint) }
|
31
30
|
end
|
32
31
|
|
33
32
|
describe 'number of geo points' do
|
@@ -36,15 +35,15 @@ describe Routing::Parser::HereSimple do
|
|
36
35
|
let(:maneuver_size) { json_response["response"]["route"].first["leg"].inject(0) { |sum, leg| sum + leg["maneuver"].size } }
|
37
36
|
|
38
37
|
it 'has the length of all maneuvers minus the duplicate ones at the touching points' do
|
39
|
-
|
38
|
+
expect(subject.size).to eq(maneuver_size - leg_touching_point_size)
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
42
|
describe 'coordinates' do
|
44
43
|
it 'sets the calculated latitude and longitude for each geo point' do
|
45
44
|
subject.each do |geo_point|
|
46
|
-
geo_point.lat.
|
47
|
-
geo_point.lng.
|
45
|
+
expect(geo_point.lat).to be
|
46
|
+
expect(geo_point.lng).to be
|
48
47
|
end
|
49
48
|
end
|
50
49
|
end
|
@@ -53,13 +52,13 @@ describe Routing::Parser::HereSimple do
|
|
53
52
|
subject { described_class.new(response).to_geo_points.select(&:waypoint?) }
|
54
53
|
|
55
54
|
it 'includes the same number of waypoints as passed in' do
|
56
|
-
|
55
|
+
expect(subject.size).to eq(original_geo_points.size)
|
57
56
|
end
|
58
57
|
|
59
58
|
it 'sets original_lat and original_lng on the waypoints' do
|
60
59
|
subject.each_with_index do |geo_point, index|
|
61
|
-
geo_point.original_lat.
|
62
|
-
geo_point.original_lng.
|
60
|
+
expect(geo_point.original_lat).to eq(original_geo_points[index].lat)
|
61
|
+
expect(geo_point.original_lng).to eq(original_geo_points[index].lng)
|
63
62
|
end
|
64
63
|
end
|
65
64
|
|
@@ -2,12 +2,11 @@ require 'spec_helper'
|
|
2
2
|
require 'json'
|
3
3
|
|
4
4
|
describe Routing::Parser::NavteqSimple do
|
5
|
-
|
6
5
|
context 'with a error response' do
|
7
6
|
let(:error_response) { fixture('navteq/error_response.json') }
|
8
7
|
|
9
8
|
it 'should throw an RoutingFailed error' do
|
10
|
-
|
9
|
+
expect{ described_class.new(error_response) }.to raise_error(Routing::Parser::RoutingFailed)
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
@@ -16,7 +15,7 @@ describe Routing::Parser::NavteqSimple do
|
|
16
15
|
let(:json_response) { JSON.parse(response) }
|
17
16
|
let(:original_geo_points) do
|
18
17
|
json_response['Response']['Route'].first['Waypoint'].collect do |waypoint|
|
19
|
-
|
18
|
+
double({
|
20
19
|
lat: waypoint['OriginalPosition']['Latitude'],
|
21
20
|
lng: waypoint['OriginalPosition']['Longitude']
|
22
21
|
})
|
@@ -27,7 +26,7 @@ describe Routing::Parser::NavteqSimple do
|
|
27
26
|
subject { described_class.new(response).to_geo_points }
|
28
27
|
|
29
28
|
it 'returns geopoints' do
|
30
|
-
subject.each { |point| point.
|
29
|
+
subject.each { |point| expect(point).to be_a(::Routing::GeoPoint) }
|
31
30
|
end
|
32
31
|
|
33
32
|
describe 'number of geo points' do
|
@@ -36,15 +35,15 @@ describe Routing::Parser::NavteqSimple do
|
|
36
35
|
let(:maneuver_size) { json_response["Response"]["Route"].first["Leg"].inject(0) { |sum, leg| sum + leg["Maneuver"].size } }
|
37
36
|
|
38
37
|
it 'has the length of all maneuvers minus the duplicate ones at the touching points' do
|
39
|
-
|
38
|
+
expect(subject.size).to eq(maneuver_size - leg_touching_point_size)
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
42
|
describe 'coordinates' do
|
44
43
|
it 'sets the calculated latitude and longitude for each geo point' do
|
45
44
|
subject.each do |geo_point|
|
46
|
-
geo_point.lat.
|
47
|
-
geo_point.lng.
|
45
|
+
expect(geo_point.lat).to be
|
46
|
+
expect(geo_point.lng).to be
|
48
47
|
end
|
49
48
|
end
|
50
49
|
end
|
@@ -53,13 +52,13 @@ describe Routing::Parser::NavteqSimple do
|
|
53
52
|
subject { described_class.new(response).to_geo_points.select(&:waypoint?) }
|
54
53
|
|
55
54
|
it 'includes the same number of waypoints as passed in' do
|
56
|
-
|
55
|
+
expect(subject.size).to eq(original_geo_points.size)
|
57
56
|
end
|
58
57
|
|
59
58
|
it 'sets original_lat and original_lng on the waypoints' do
|
60
59
|
subject.each_with_index do |geo_point, index|
|
61
|
-
geo_point.original_lat.
|
62
|
-
geo_point.original_lng.
|
60
|
+
expect(geo_point.original_lat).to eq(original_geo_points[index].lat)
|
61
|
+
expect(geo_point.original_lng).to eq(original_geo_points[index].lng)
|
63
62
|
end
|
64
63
|
end
|
65
64
|
|
@@ -78,4 +77,4 @@ describe Routing::Parser::NavteqSimple do
|
|
78
77
|
end
|
79
78
|
end
|
80
79
|
end
|
81
|
-
end
|
80
|
+
end
|
data/spec/routing_spec.rb
CHANGED
@@ -1,23 +1,21 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Routing do
|
4
|
-
|
5
4
|
context 'creating a new instance' do
|
6
|
-
|
7
|
-
let(:adapter) { mock }
|
5
|
+
let(:adapter) { double }
|
8
6
|
|
9
7
|
it 'can be called without arguments' do
|
10
8
|
expect { Routing.new }.to_not raise_error
|
11
9
|
end
|
12
10
|
|
13
11
|
it 'uses the default adapter, if no adapter is passed' do
|
14
|
-
described_class.default_adapter.
|
15
|
-
subject.calculate(
|
12
|
+
expect(described_class.default_adapter).to receive(:calculate)
|
13
|
+
subject.calculate(double, double)
|
16
14
|
end
|
17
15
|
|
18
16
|
it 'takes the passed adapter, if given' do
|
19
|
-
adapter.
|
20
|
-
described_class.new(adapter).calculate(
|
17
|
+
expect(adapter).to receive(:calculate)
|
18
|
+
described_class.new(adapter).calculate(double, double)
|
21
19
|
end
|
22
20
|
|
23
21
|
it 'takes a configuration block' do
|
@@ -25,58 +23,48 @@ describe Routing do
|
|
25
23
|
end
|
26
24
|
|
27
25
|
it 'passes itself to the configuration block' do
|
28
|
-
described_class.new { |r| r.
|
26
|
+
described_class.new { |r| expect(r).to be_instance_of(described_class) }
|
29
27
|
end
|
30
|
-
|
31
28
|
end
|
32
29
|
|
33
30
|
describe '#calculate' do
|
34
|
-
let(:geo_points) { [
|
35
|
-
let(:adapter) {
|
31
|
+
let(:geo_points) { [double(lat: 1, lng: 2), double(lat: 3, lng: 4), double(lat: 5, lng: 6)] }
|
32
|
+
let(:adapter) { double(calculate: geo_points) }
|
36
33
|
|
37
34
|
subject { described_class.new(adapter) }
|
38
35
|
|
39
36
|
it 'should call the adapter' do
|
40
|
-
adapter.
|
37
|
+
expect(adapter).to receive(:calculate).with(geo_points)
|
41
38
|
subject.calculate(geo_points)
|
42
39
|
end
|
43
40
|
|
44
41
|
it 'should call each middleware in the given order' do
|
45
42
|
first_middleware = double(Routing::Middleware)
|
46
|
-
first_middleware.
|
43
|
+
expect(first_middleware).to receive(:calculate).
|
47
44
|
with(geo_points).and_yield(geo_points)
|
48
45
|
|
49
46
|
second_middleware = double(Routing::Middleware)
|
50
|
-
second_middleware.
|
47
|
+
expect(second_middleware).to receive(:calculate).
|
51
48
|
with(geo_points)
|
52
49
|
|
53
|
-
subject.
|
50
|
+
allow(subject).to receive(:middlewares).and_return([first_middleware, second_middleware])
|
54
51
|
|
55
52
|
subject.calculate(geo_points)
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
59
56
|
context 'using the middleware' do
|
60
|
-
|
61
57
|
it 'has an empty array of middlewares by default' do
|
62
|
-
subject.middlewares.
|
63
|
-
subject.
|
58
|
+
expect(subject.middlewares).to be_an(Array)
|
59
|
+
expect(subject.middlewares.size).to eq(0)
|
64
60
|
end
|
65
61
|
|
66
62
|
describe '#use' do
|
67
63
|
it 'appends the new middleware to the stack' do
|
68
64
|
subject.use(:hello)
|
69
65
|
subject.use(:world)
|
70
|
-
subject.middlewares.
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe '#middlewares' do
|
75
|
-
it 'replaces all middlewares' do
|
76
|
-
subject.use(:original)
|
77
|
-
subject.middlewares = :first, :second
|
78
|
-
subject.middlewares.should == [:first, :second]
|
66
|
+
expect(subject.middlewares).to eq([:hello, :world])
|
79
67
|
end
|
80
68
|
end
|
81
69
|
end
|
82
|
-
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: routing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Bäuerlein
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-07-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -39,20 +39,48 @@ dependencies:
|
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: smart_properties
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.0'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
57
|
name: rspec
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
45
59
|
requirements:
|
46
60
|
- - ">="
|
47
61
|
- !ruby/object:Gem::Version
|
48
|
-
version: 2.
|
62
|
+
version: '2.11'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.11'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rake
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
49
77
|
type: :development
|
50
78
|
prerelease: false
|
51
79
|
version_requirements: !ruby/object:Gem::Requirement
|
52
80
|
requirements:
|
53
81
|
- - ">="
|
54
82
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
83
|
+
version: '0'
|
56
84
|
description: "\n Provides a generic interface for routing services that can by
|
57
85
|
used to calculate directions between geolocations.\n Makes parsing and use-case
|
58
86
|
specific data handling easy trough an extendable middleware stack.\n "
|
@@ -73,6 +101,7 @@ files:
|
|
73
101
|
- lib/routing/adapter.rb
|
74
102
|
- lib/routing/adapter/here.rb
|
75
103
|
- lib/routing/adapter/navteq.rb
|
104
|
+
- lib/routing/adapter/rest_adapter.rb
|
76
105
|
- lib/routing/adapter/test.rb
|
77
106
|
- lib/routing/geo_point.rb
|
78
107
|
- lib/routing/middleware.rb
|
@@ -112,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
141
|
version: '0'
|
113
142
|
requirements: []
|
114
143
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.2.
|
144
|
+
rubygems_version: 2.2.2
|
116
145
|
signing_key:
|
117
146
|
specification_version: 4
|
118
147
|
summary: A ruby interface for route calculation services
|