london-bike-hire-cli 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +1 -0
  4. data/README.md +19 -17
  5. data/lib/london_bike_hire_cli/application.rb +8 -1
  6. data/lib/london_bike_hire_cli/basic_renderer.rb +15 -22
  7. data/lib/london_bike_hire_cli/color_helper.rb +24 -0
  8. data/lib/london_bike_hire_cli/controller.rb +21 -31
  9. data/lib/london_bike_hire_cli/feed_parser.rb +9 -10
  10. data/lib/london_bike_hire_cli/queries/stations_by_name.rb +9 -0
  11. data/lib/london_bike_hire_cli/queries/stations_near.rb +5 -0
  12. data/lib/london_bike_hire_cli/query_response.rb +4 -14
  13. data/lib/london_bike_hire_cli/repository/in_memory_store_adapter.rb +69 -0
  14. data/lib/london_bike_hire_cli/repository/repo.rb +39 -0
  15. data/lib/london_bike_hire_cli/repository/spatial_search_adapter.rb +28 -0
  16. data/lib/london_bike_hire_cli/repository/station_repo.rb +35 -0
  17. data/lib/london_bike_hire_cli/repository/station_store.rb +22 -0
  18. data/lib/london_bike_hire_cli/station.rb +4 -0
  19. data/lib/london_bike_hire_cli/station_not_found_error.rb +3 -0
  20. data/lib/london_bike_hire_cli/version.rb +1 -1
  21. data/lib/london_bike_hire_cli/views/error.erb +5 -0
  22. data/lib/london_bike_hire_cli/views/stations.erb +11 -0
  23. data/lib/london_bike_hire_cli.rb +12 -7
  24. data/london-bike-hire-cli.gemspec +3 -2
  25. data/spec/controller_spec.rb +29 -61
  26. data/spec/feed_parser_spec.rb +10 -12
  27. data/spec/station_repo_spec.rb +148 -0
  28. data/spec/support/test_datasource.rb +8 -4
  29. data/test.rb +1 -0
  30. metadata +17 -13
  31. data/lib/london_bike_hire_cli/spatial_search.rb +0 -20
  32. data/lib/london_bike_hire_cli/station_adapter.rb +0 -19
  33. data/lib/london_bike_hire_cli/station_repository.rb +0 -51
  34. data/spec/spatial_search_spec.rb +0 -27
  35. data/spec/station_adapter_spec.rb +0 -29
  36. data/spec/station_respository_spec.rb +0 -117
@@ -1,15 +1,20 @@
1
+ module LondonBikeHireCli
2
+ DEFAULT_SEARCH_LIMIT = 5
3
+ end
4
+
1
5
  require_relative 'london_bike_hire_cli/application'
2
6
  require_relative 'london_bike_hire_cli/basic_renderer'
3
7
  require_relative 'london_bike_hire_cli/controller'
4
8
  require_relative 'london_bike_hire_cli/feed_parser'
5
9
  require_relative 'london_bike_hire_cli/geocoding_adapter'
6
10
  require_relative 'london_bike_hire_cli/query_response'
7
- require_relative 'london_bike_hire_cli/spatial_search'
8
11
  require_relative 'london_bike_hire_cli/station'
9
- require_relative 'london_bike_hire_cli/station_adapter'
10
- require_relative 'london_bike_hire_cli/station_repository'
12
+ require_relative 'london_bike_hire_cli/repository/repo'
13
+ require_relative 'london_bike_hire_cli/repository/in_memory_store_adapter'
14
+ require_relative 'london_bike_hire_cli/repository/station_store'
15
+ require_relative 'london_bike_hire_cli/repository/station_repo'
16
+ require_relative 'london_bike_hire_cli/repository/spatial_search_adapter'
17
+ require_relative 'london_bike_hire_cli/queries/stations_by_name'
18
+ require_relative 'london_bike_hire_cli/queries/stations_near'
19
+ require_relative 'london_bike_hire_cli/station_not_found_error'
11
20
  require_relative 'london_bike_hire_cli/version'
12
-
13
- module LondonBikeHireCli
14
- DEFAULT_SEARCH_LIMIT = 5
15
- end
@@ -8,10 +8,11 @@ Gem::Specification.new do |spec|
8
8
  spec.version = LondonBikeHireCli::VERSION
9
9
  spec.authors = ['Rob Murray']
10
10
  spec.email = ['robmurray17@gmail.com']
11
- spec.summary = %q(A command line interface to London's Bike Hire API.)
12
- spec.description = %q(Find information about London's Bike Hire stations from command line interface.)
11
+ spec.summary = "A command line interface to London's Bike Hire API."
12
+ spec.description = "Find information about London's Bike Hire stations from command line interface."
13
13
  spec.homepage = 'https://github.com/rob-murray/london-bike-hire-cli'
14
14
  spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 2.0.0'
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -15,14 +15,14 @@ RSpec.describe LondonBikeHireCli::Controller do
15
15
 
16
16
  describe '#find_by_id' do
17
17
  it 'should request station from repository' do
18
- expect(repository).to receive(:find_by_id).with(1)
18
+ expect(repository).to receive(:find).with(1)
19
19
 
20
20
  subject.find_by_id(1)
21
21
  end
22
22
 
23
23
  context 'given a string argument' do
24
24
  it 'should request station from repository' do
25
- expect(repository).to receive(:find_by_id).with(1)
25
+ expect(repository).to receive(:find).with(1)
26
26
 
27
27
  subject.find_by_id('1')
28
28
  end
@@ -30,7 +30,7 @@ RSpec.describe LondonBikeHireCli::Controller do
30
30
 
31
31
  context 'given repository raising not found error' do
32
32
  it 'does not raise_error' do
33
- allow(repository).to receive(:find_by_id).and_raise(LondonBikeHireCli::StationRepository::StationNotFound)
33
+ allow(repository).to receive(:find).and_raise(LondonBikeHireCli::StationNotFoundError)
34
34
 
35
35
  expect do
36
36
  subject.find_by_id(1)
@@ -41,15 +41,18 @@ RSpec.describe LondonBikeHireCli::Controller do
41
41
 
42
42
  describe '#where' do
43
43
  context 'given a request with name parameter' do
44
- it 'should request stations from repository' do
45
- expect(repository).to receive(:find_by_name).with('kings')
44
+ it 'should request stations from repository with query' do
45
+ expect(repository).to receive(:query) do |arg|
46
+ expect(arg.search_term).to eq('kings')
47
+ end
46
48
 
47
49
  subject.where(params: { name: 'kings' })
48
50
  end
49
51
 
50
52
  context 'given repository raising not found error' do
51
53
  it 'does not raise_error' do
52
- allow(repository).to receive(:find_by_name).and_raise(LondonBikeHireCli::StationRepository::StationNotFound)
54
+ # TODO: change this
55
+ allow(repository).to receive(:query).and_raise(LondonBikeHireCli::StationNotFoundError)
53
56
 
54
57
  expect do
55
58
  subject.where(params: { name: 'kings' })
@@ -60,8 +63,6 @@ RSpec.describe LondonBikeHireCli::Controller do
60
63
  end
61
64
 
62
65
  describe '#nearest' do
63
- let(:stations) { TestDatasource.new.fetch.values }
64
- let(:spatial_search) { double.as_null_object }
65
66
  let(:geocoder) { double.as_null_object }
66
67
  let(:geocoded_point) { { lat: 51.5309584, long: -0.1215387 } }
67
68
 
@@ -71,7 +72,7 @@ RSpec.describe LondonBikeHireCli::Controller do
71
72
  end
72
73
 
73
74
  it 'does not process request' do
74
- expect(repository).not_to receive(:all)
75
+ expect(repository).not_to receive(:query)
75
76
 
76
77
  subject.nearest(params: params)
77
78
  end
@@ -80,13 +81,11 @@ RSpec.describe LondonBikeHireCli::Controller do
80
81
  context 'given a request with search_term parameter' do
81
82
  let(:search_term) { 'N19AE' }
82
83
  before do
83
- allow(repository).to receive(:all).and_return(stations)
84
- allow(repository).to receive(:find_by_id).and_return(double.as_null_object)
84
+ allow(repository).to receive(:find).and_return(double.as_null_object)
85
85
  allow(geocoder).to receive(:geocode).and_return(geocoded_point)
86
- allow(spatial_search).to receive(:nearest).and_return([1])
86
+ allow(repository).to receive(:query)
87
87
 
88
88
  subject.geocoder = geocoder
89
- subject.spatial_service = spatial_search
90
89
  end
91
90
 
92
91
  it 'geocodes search_term via service' do
@@ -95,27 +94,12 @@ RSpec.describe LondonBikeHireCli::Controller do
95
94
  subject.nearest(params: { search_term: search_term })
96
95
  end
97
96
 
98
- it 'requests all stations from repository' do
99
- expect(repository).to receive(:all).and_return(stations)
100
-
101
- subject.nearest(params: { search_term: search_term })
102
- end
103
-
104
- it 'passes all stations to spatial search' do
105
- subject.spatial_service = nil
106
- expect(LondonBikeHireCli::SpatialSearch).to receive(:new).and_return(spatial_search)
107
-
108
- subject.nearest(params: { search_term: search_term })
109
- end
110
-
111
- it 'requests nearest ids from geocoded point' do
112
- expect(spatial_search).to receive(:nearest).and_return([1])
113
-
114
- subject.nearest(params: { search_term: search_term })
115
- end
116
-
117
- it 'retreives stations matched by search' do
118
- expect(repository).to receive(:find_by_id).with(1)
97
+ it 'requests stations from repository by query' do
98
+ expect(repository).to receive(:query) do |arg|
99
+ expect(arg.lat).to eq(geocoded_point[:lat])
100
+ expect(arg.long).to eq(geocoded_point[:long])
101
+ expect(arg.limit).to eq(LondonBikeHireCli::DEFAULT_SEARCH_LIMIT)
102
+ end
119
103
 
120
104
  subject.nearest(params: { search_term: search_term })
121
105
  end
@@ -127,49 +111,33 @@ RSpec.describe LondonBikeHireCli::Controller do
127
111
  end
128
112
 
129
113
  it 'does not request stations from repository' do
130
- expect(repository).not_to receive(:all)
114
+ expect(repository).not_to receive(:query)
131
115
  end
132
116
  end
133
117
  end
134
118
 
135
119
  context 'given a request with id parameter' do
136
120
  let(:search_id) { 1 }
121
+ let(:station) { double('Station', id: 1, position: geocoded_point) }
137
122
  before do
138
- allow(repository).to receive(:all).and_return(stations)
139
- allow(repository).to receive(:find_by_id).and_return(double.as_null_object)
140
- allow(spatial_search).to receive(:nearest).and_return([1, 2])
123
+ allow(repository).to receive(:find).and_return(station)
124
+ allow(repository).to receive(:query)
141
125
 
142
126
  subject.geocoder = geocoder
143
- subject.spatial_service = spatial_search
144
127
  end
145
128
 
146
129
  it 'requests station from repository' do
147
- expect(repository).to receive(:find_by_id).with(search_id)
148
-
149
- subject.nearest(params: { id: search_id })
150
- end
151
-
152
- it 'requests all stations from repository' do
153
- expect(repository).to receive(:all).and_return(stations)
154
-
155
- subject.nearest(params: { id: search_id })
156
- end
157
-
158
- it 'passes all stations to spatial search' do
159
- subject.spatial_service = nil
160
- expect(LondonBikeHireCli::SpatialSearch).to receive(:new).and_return(spatial_search)
130
+ expect(repository).to receive(:find).with(search_id)
161
131
 
162
132
  subject.nearest(params: { id: search_id })
163
133
  end
164
134
 
165
- it 'requests nearest ids from geocoded point' do
166
- expect(spatial_search).to receive(:nearest).and_return([1])
167
-
168
- subject.nearest(params: { id: search_id })
169
- end
170
-
171
- it 'retreives stations matched by search' do
172
- expect(repository).to receive(:find_by_id).with(1)
135
+ it 'requests stations from repository by query' do
136
+ expect(repository).to receive(:query) do |arg|
137
+ expect(arg.lat).to eq(geocoded_point[:lat])
138
+ expect(arg.long).to eq(geocoded_point[:long])
139
+ expect(arg.limit).to eq(LondonBikeHireCli::DEFAULT_SEARCH_LIMIT)
140
+ end
173
141
 
174
142
  subject.nearest(params: { id: search_id })
175
143
  end
@@ -8,35 +8,33 @@ RSpec.describe LondonBikeHireCli::FeedParser do
8
8
  expect(subject.fetch).not_to be_nil
9
9
  end
10
10
 
11
- it 'parses expected number of Bike Stations' do
12
- results = subject.fetch
13
- expect(results.keys.count).to eq(747 + 1)
11
+ it 'returns query response' do
12
+ expect(subject.fetch).to be_instance_of(LondonBikeHireCli::QueryResponse)
14
13
  end
15
14
 
16
- it 'has the feed update time' do
15
+ it 'parses expected number of Bike Stations' do
17
16
  results = subject.fetch
18
- expect(results).to have_key(:last_update)
17
+ expect(results.size).to eq(747)
19
18
  end
20
19
 
21
- it 'has integer for all Stations' do
20
+ it 'has returns array of Stations' do
22
21
  results = subject.fetch
23
- results.delete(:last_update)
24
22
 
25
- expect(results.keys).to all(be_an(Integer))
23
+ # TODO fix the enumerator thing
24
+ expect(results.map { |s| s }).to all(be_an(LondonBikeHireCli::Station))
26
25
  end
27
26
 
28
27
  it 'has integer for all Station IDs' do
29
28
  results = subject.fetch
30
- results.delete(:last_update)
31
- stations = results.values
32
- ids = stations.map(&:id)
29
+ ids = results.map(&:id)
33
30
 
34
31
  expect(ids).to all(be_an(Integer))
35
32
  end
36
33
 
37
34
  it 'has parsed date time from feed update time' do
38
35
  results = subject.fetch
39
- expect(results[:last_update]).to eq(Time.new(2014, 8, 10, 10, 56, 01, '+01:00'))
36
+ expected_time = Time.new(2014, 8, 10, 10, 56, 01, '+01:00')
37
+ expect(results.last_update).to eq(expected_time)
40
38
  end
41
39
  end
42
40
  end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe LondonBikeHireCli::Repository::StationRepo do
4
+ let(:test_datasource) { TestDatasource.new }
5
+ let(:adapter) { LondonBikeHireCli::Repository::StationStore.new(test_datasource.fetch) }
6
+ before do
7
+ LondonBikeHireCli::Repository::Repo.register(adapter)
8
+ end
9
+ subject { described_class.new }
10
+
11
+ describe '#all' do
12
+ context 'given feed_parser returns dataset' do
13
+ it 'should return expected number of results' do
14
+ results = subject.all
15
+
16
+ expect(results.size).to eq(2)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '#find' do
22
+ context 'given feed_parser returns dataset' do
23
+ it 'should return expected number of results' do
24
+ result = subject.find(1)
25
+
26
+ expect(result).to be
27
+ end
28
+
29
+ it 'should return expected result' do
30
+ result = subject.find(1)
31
+
32
+ expect(result.name).to eq('test-station-1')
33
+ end
34
+
35
+ context 'given a request for an id that does not exist' do
36
+ it 'should raise error' do
37
+ expect do
38
+ subject.find(99)
39
+ end.to raise_error
40
+ end
41
+ end
42
+
43
+ context 'given a request for more than one id' do
44
+ xit 'should return expected number of results' do
45
+ results = subject.find(1, 2)
46
+
47
+ expect(results.size).to eq(2)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#query' do
54
+ describe 'for stations by name' do
55
+ let(:query) { LondonBikeHireCli::Queries::StationsByName.new('test-station-1') }
56
+
57
+ context 'given feed_parser returns dataset' do
58
+ it 'should return expected number of results' do
59
+ results = subject.query(query)
60
+
61
+ expect(results.size).to eq(1)
62
+ end
63
+
64
+ it 'should return expected result' do
65
+ result = subject.query(query).first
66
+
67
+ expect(result.name).to eq('test-station-1')
68
+ end
69
+
70
+ context 'given a request for an id that does not exist' do
71
+ let(:query) { LondonBikeHireCli::Queries::StationsByName.new('foo') }
72
+
73
+ it 'should not raise error' do
74
+ expect do
75
+ subject.query(query)
76
+ end.not_to raise_error
77
+ end
78
+
79
+ it 'should return empty array' do
80
+ expect(subject.query(query).size).to eq(0)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe 'for stations near location' do
87
+ let(:point) { { lat: 51.50810309, long: -0.12602103 } }
88
+ let(:query) { LondonBikeHireCli::Queries::StationsNear.new(point[:lat], point[:long], 5) }
89
+
90
+ context 'given feed_parser returns dataset' do
91
+ it 'should return expected number of results' do
92
+ results = subject.query(query)
93
+
94
+ expect(results.size).to eq(2)
95
+ end
96
+
97
+ it 'should return expected result' do
98
+ result = subject.query(query).first
99
+
100
+ expect(result.name).to eq('test-station-2')
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ describe 'integration tests', vcr: { cassette_name: 'feed_xml' } do
107
+ let(:test_datasource) { LondonBikeHireCli::FeedParser.new }
108
+
109
+ describe '#find' do
110
+ it 'should return expected number of results' do
111
+ result = subject.find(777)
112
+
113
+ expect(result).to be
114
+ end
115
+
116
+ it 'should return expected result' do
117
+ result = subject.find(777)
118
+
119
+ expect(result.name).to eq('Limburg Road, Clapham Common')
120
+ end
121
+ end
122
+
123
+ describe '#query' do
124
+ let(:query) { LondonBikeHireCli::Queries::StationsByName.new('kings') }
125
+
126
+ it 'should return expected number of results' do
127
+ results = subject.query(query)
128
+
129
+ expect(results.size).to eq(3)
130
+ end
131
+
132
+ it 'should return expected result' do
133
+ results = subject.query(query)
134
+ actual_ids = results.map(&:id)
135
+
136
+ expect(actual_ids).to include(283, 439, 594)
137
+ end
138
+ end
139
+
140
+ describe '#all' do
141
+ it 'should return expected number of results' do
142
+ results = subject.all
143
+
144
+ expect(results.size).to eq(747)
145
+ end
146
+ end
147
+ end
148
+ end
@@ -1,7 +1,13 @@
1
1
  class TestDatasource
2
2
  def fetch
3
+ stations.values
4
+ end
5
+
6
+ private
7
+
8
+ def stations
3
9
  {
4
- 1 => TestStation.new(
10
+ 1 => LondonBikeHireCli::Station.new(
5
11
  id: 1,
6
12
  name: 'test-station-1',
7
13
  docks_total: 30,
@@ -9,7 +15,7 @@ class TestDatasource
9
15
  lat: 51.53005939,
10
16
  long: -0.120973687
11
17
  ),
12
- 2 => TestStation.new(
18
+ 2 => LondonBikeHireCli::Station.new(
13
19
  id: 2,
14
20
  name: 'test-station-2',
15
21
  docks_total: 30,
@@ -19,6 +25,4 @@ class TestDatasource
19
25
  )
20
26
  }
21
27
  end
22
-
23
- TestStation = OpenStruct
24
28
  end
data/test.rb CHANGED
@@ -2,5 +2,6 @@ require 'rubygems'
2
2
  require 'bundler'
3
3
  Bundler.setup
4
4
  require 'london_bike_hire_cli'
5
+ require 'byebug'
5
6
 
6
7
  LondonBikeHireCli::Application.new.run
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: london-bike-hire-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Murray
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-28 00:00:00.000000000 Z
11
+ date: 2015-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -243,15 +243,23 @@ files:
243
243
  - lib/london_bike_hire_cli.rb
244
244
  - lib/london_bike_hire_cli/application.rb
245
245
  - lib/london_bike_hire_cli/basic_renderer.rb
246
+ - lib/london_bike_hire_cli/color_helper.rb
246
247
  - lib/london_bike_hire_cli/controller.rb
247
248
  - lib/london_bike_hire_cli/feed_parser.rb
248
249
  - lib/london_bike_hire_cli/geocoding_adapter.rb
250
+ - lib/london_bike_hire_cli/queries/stations_by_name.rb
251
+ - lib/london_bike_hire_cli/queries/stations_near.rb
249
252
  - lib/london_bike_hire_cli/query_response.rb
250
- - lib/london_bike_hire_cli/spatial_search.rb
253
+ - lib/london_bike_hire_cli/repository/in_memory_store_adapter.rb
254
+ - lib/london_bike_hire_cli/repository/repo.rb
255
+ - lib/london_bike_hire_cli/repository/spatial_search_adapter.rb
256
+ - lib/london_bike_hire_cli/repository/station_repo.rb
257
+ - lib/london_bike_hire_cli/repository/station_store.rb
251
258
  - lib/london_bike_hire_cli/station.rb
252
- - lib/london_bike_hire_cli/station_adapter.rb
253
- - lib/london_bike_hire_cli/station_repository.rb
259
+ - lib/london_bike_hire_cli/station_not_found_error.rb
254
260
  - lib/london_bike_hire_cli/version.rb
261
+ - lib/london_bike_hire_cli/views/error.erb
262
+ - lib/london_bike_hire_cli/views/stations.erb
255
263
  - london-bike-hire-cli.gemspec
256
264
  - spec/controller_spec.rb
257
265
  - spec/feed_parser_spec.rb
@@ -259,10 +267,8 @@ files:
259
267
  - spec/fixtures/n19ae_geocode.yml
260
268
  - spec/fixtures/no_results_geocode.yml
261
269
  - spec/geocoding_adapter_spec.rb
262
- - spec/spatial_search_spec.rb
263
270
  - spec/spec_helper.rb
264
- - spec/station_adapter_spec.rb
265
- - spec/station_respository_spec.rb
271
+ - spec/station_repo_spec.rb
266
272
  - spec/station_spec.rb
267
273
  - spec/support/test_datasource.rb
268
274
  - spec/support/vcr.rb
@@ -279,7 +285,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
279
285
  requirements:
280
286
  - - ">="
281
287
  - !ruby/object:Gem::Version
282
- version: '0'
288
+ version: 2.0.0
283
289
  required_rubygems_version: !ruby/object:Gem::Requirement
284
290
  requirements:
285
291
  - - ">="
@@ -287,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
293
  version: '0'
288
294
  requirements: []
289
295
  rubyforge_project:
290
- rubygems_version: 2.2.2
296
+ rubygems_version: 2.4.6
291
297
  signing_key:
292
298
  specification_version: 4
293
299
  summary: A command line interface to London's Bike Hire API.
@@ -298,10 +304,8 @@ test_files:
298
304
  - spec/fixtures/n19ae_geocode.yml
299
305
  - spec/fixtures/no_results_geocode.yml
300
306
  - spec/geocoding_adapter_spec.rb
301
- - spec/spatial_search_spec.rb
302
307
  - spec/spec_helper.rb
303
- - spec/station_adapter_spec.rb
304
- - spec/station_respository_spec.rb
308
+ - spec/station_repo_spec.rb
305
309
  - spec/station_spec.rb
306
310
  - spec/support/test_datasource.rb
307
311
  - spec/support/vcr.rb
@@ -1,20 +0,0 @@
1
- require 'kdtree'
2
-
3
- module LondonBikeHireCli
4
- class SpatialSearch
5
- def initialize(datasource)
6
- @stations = Kdtree.new(datasource)
7
- end
8
-
9
- # Public: Return the IDs of the nearest n stations
10
- # point - a 2d point; { lat: x.x, long: x.x }
11
- # limit - The maximum number of results
12
- def nearest(point, limit = DEFAULT_SEARCH_LIMIT)
13
- stations.nearestk(point[:lat], point[:long], limit)
14
- end
15
-
16
- private
17
-
18
- attr_reader :stations
19
- end
20
- end
@@ -1,19 +0,0 @@
1
- module LondonBikeHireCli
2
- class StationAdapter
3
- def initialize(stations)
4
- @stations = stations
5
- end
6
-
7
- # Public: Produce array of station triples
8
- # E.g. [51.50810309, -0.12602103, 2]
9
- # As used by kdtree
10
- #
11
- def to_triples
12
- stations.map { |station| [station.lat, station.long, station.id] }
13
- end
14
-
15
- private
16
-
17
- attr_reader :stations
18
- end
19
- end
@@ -1,51 +0,0 @@
1
- module LondonBikeHireCli
2
- class StationRepository
3
- class StationNotFound < StandardError; end
4
-
5
- def initialize(datasource)
6
- @datasource = datasource
7
- end
8
-
9
- def all
10
- return_query_obj(stations.values)
11
- end
12
-
13
- def find_by_id(*station_ids)
14
- if station_ids.size == 1
15
- matched_stations = stations[station_ids.first]
16
- else
17
- matched_stations = stations.values_at(*station_ids)
18
- end
19
-
20
- fail StationNotFound unless matched_stations
21
-
22
- return_query_obj(matched_stations)
23
- end
24
-
25
- def find_by_name(station_name)
26
- search_term = normalize_search_term(station_name)
27
- results = stations.select { |_id, station| station.name.downcase.include?(search_term) }
28
- return_query_obj(results.values)
29
- end
30
-
31
- private
32
-
33
- attr_reader :datasource, :last_update
34
-
35
- def normalize_search_term(input)
36
- input.downcase
37
- end
38
-
39
- def return_query_obj(results)
40
- QueryResponse.new(last_update: last_update, results: Array(results))
41
- end
42
-
43
- def stations
44
- @stations ||= begin
45
- results = datasource.fetch
46
- @last_update = results.delete(:last_update)
47
- results
48
- end
49
- end
50
- end
51
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe LondonBikeHireCli::SpatialSearch do
4
- let(:point_1) { [51.53005939, -0.120973687, 1] }
5
- let(:point_2) { [51.50810309, -0.12602103, 2] }
6
- let(:datasource) { [point_1, point_2] }
7
- subject { described_class.new(datasource) }
8
-
9
- describe '#nearest' do
10
- context 'with datasource' do
11
- let(:request) { { lat: 51.5309, long: -0.1215 } }
12
- it 'returns results ordered by distance' do
13
- results = subject.nearest(request)
14
-
15
- expect(results).to eq([1, 2])
16
- end
17
-
18
- context 'given a limit request' do
19
- it 'returns correct number of results' do
20
- results = subject.nearest(request, 1)
21
-
22
- expect(results.size).to eq(1)
23
- end
24
- end
25
- end
26
- end
27
- end