routing 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|