cta_redux 0.2.0 → 0.3.1
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/CONTRIBUTING.md +26 -0
- data/README.md +1 -1
- data/lib/cta_redux/api/api_response.rb +10 -0
- data/lib/cta_redux/api/bus_tracker.rb +69 -5
- data/lib/cta_redux/api/customer_alerts.rb +47 -4
- data/lib/cta_redux/api/train_tracker.rb +31 -13
- data/lib/cta_redux/bus_tracker.rb +42 -5
- data/lib/cta_redux/customer_alerts.rb +37 -1
- data/lib/cta_redux/faraday_middleware/simple_cache.rb +2 -0
- data/lib/cta_redux/models/agency.rb +22 -0
- data/lib/cta_redux/models/bus.rb +97 -18
- data/lib/cta_redux/models/calendar.rb +28 -0
- data/lib/cta_redux/models/route.rb +71 -9
- data/lib/cta_redux/models/shape.rb +20 -0
- data/lib/cta_redux/models/stop.rb +68 -0
- data/lib/cta_redux/models/stop_time.rb +33 -0
- data/lib/cta_redux/models/train.rb +80 -16
- data/lib/cta_redux/models/transfer.rb +17 -0
- data/lib/cta_redux/models/trip.rb +54 -9
- data/lib/cta_redux/train_tracker.rb +38 -1
- data/lib/cta_redux/version.rb +1 -1
- data/spec/bus_tracker_spec.rb +4 -4
- data/spec/train_tracker_spec.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f83f5bf3b8bfc681998bdaa39b19c45a77a8c388
|
4
|
+
data.tar.gz: 371f9733b0decd55ea6858f9e39b7cd8337a0ebe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 996e04cc55d7f1d65aaa9703676aac5c818d1096b152f48a7d2aea9e2edc24a6aa8fed1c64cc4d2ceb6ca84de870c614ffa3b659707fd2533064f9deb5bcc016
|
7
|
+
data.tar.gz: 33b0201a8c53886c123e5ce98b22b0f3254b7af914044da8160821ce9f095162b632fce2c68ea377613d00452e150a5c89d31b2885b4a64ee4190e8a021248c9
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Notes
|
2
|
+
|
3
|
+
When running the gem from a git checkout, you'll need to unzip the CTA database yourself.
|
4
|
+
|
5
|
+
````cd data && gunzip cta-gtfs.db.gz````
|
6
|
+
|
7
|
+
# How to reload CTA GTFS data
|
8
|
+
|
9
|
+
Note that this will take a long time - there are several million stop_time records.
|
10
|
+
|
11
|
+
1. cd data && curl 'http://www.transitchicago.com/downloads/sch_data/<latest file>' > gtfs.zip && unzip gtfs.zip
|
12
|
+
|
13
|
+
2. cd ../script && for i in `ls ../data/*.txt`; do echo $i; ./gtfs_to_sqlite.rb $i ../data/cta-gtfs.db; done
|
14
|
+
|
15
|
+
3. rm ../data/*{txt,htm,zip}
|
16
|
+
|
17
|
+
4. cd ../data && sqlite3 ./cta-gtfs.db
|
18
|
+
|
19
|
+
5. ANALYZE
|
20
|
+
|
21
|
+
6. VACUUM
|
22
|
+
|
23
|
+
7. gzip cta-gtfs.db
|
24
|
+
|
25
|
+
8. Commit / push / create release and gem
|
26
|
+
|
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module CTA
|
2
2
|
class API
|
3
3
|
class Error
|
4
|
+
# @return [Integer] Error code from the API. Normalized across different CTA APIs, and 0 indicates success.
|
4
5
|
attr_reader :code
|
6
|
+
|
7
|
+
# @return [String] Detailed error message, if any, from the API.
|
5
8
|
attr_reader :message
|
6
9
|
|
7
10
|
def initialize(options = {})
|
@@ -11,9 +14,16 @@ module CTA
|
|
11
14
|
end
|
12
15
|
|
13
16
|
class Response
|
17
|
+
# @return [DateTime] Timestamp from the API server, if available. Defaults to DateTime.now if unavailable.
|
14
18
|
attr_reader :timestamp
|
19
|
+
|
20
|
+
# @return [CTA::API::Error] Error information from the API
|
15
21
|
attr_reader :error
|
22
|
+
|
23
|
+
# @return [String, nil] Raw XML from the API. Only set when {CTA::BusTracker.debug} or {CTA::TrainTracker.debug} is true.
|
16
24
|
attr_reader :raw_body
|
25
|
+
|
26
|
+
# @return [Hash, nil] Parsed XML from the API. Only set when {CTA::BusTracker.debug} or {CTA::TrainTracker.debug} is true.
|
17
27
|
attr_reader :parsed_body
|
18
28
|
|
19
29
|
def initialize(parsed_body, raw_body, debug)
|
@@ -6,13 +6,15 @@ module CTA
|
|
6
6
|
class BusTracker
|
7
7
|
|
8
8
|
class VehiclesResponse < CTA::API::Response
|
9
|
+
# @return [Array<CTA::Bus>] An array with a full {CTA::Bus} object for each vehicle returned in the API, augmented
|
10
|
+
# with live details
|
9
11
|
attr_reader :vehicles
|
10
12
|
|
11
13
|
def initialize(parsed_body, raw_body, debug)
|
12
14
|
super(parsed_body, raw_body, debug)
|
13
15
|
@vehicles = Array.wrap(parsed_body["bustime_response"]["vehicle"]).map do |v|
|
14
16
|
bus = CTA::Bus.find_active_run(v["rt"], v["tmstmp"], (v["dly"] == "true")).first
|
15
|
-
bus.live
|
17
|
+
bus.live = CTA::Bus::Live.new(v)
|
16
18
|
|
17
19
|
bus
|
18
20
|
end
|
@@ -20,6 +22,7 @@ module CTA
|
|
20
22
|
end
|
21
23
|
|
22
24
|
class TimeResponse < CTA::API::Response
|
25
|
+
# @return [DateTime] Current time according to the BusTime servers which power the BusTracker API
|
23
26
|
attr_reader :timestamp
|
24
27
|
|
25
28
|
def initialize(parsed_body, raw_body, debug)
|
@@ -29,6 +32,8 @@ module CTA
|
|
29
32
|
end
|
30
33
|
|
31
34
|
class RoutesResponse < CTA::API::Response
|
35
|
+
# @return [Array<CTA::Route>] An array with a full {CTA::Route} object for each route returned by the API,
|
36
|
+
# augmented with the color that the API thinks you should be using (which is not always found in the GTFS data).
|
32
37
|
attr_reader :routes
|
33
38
|
|
34
39
|
def initialize(parsed_body, raw_body, debug)
|
@@ -43,6 +48,7 @@ module CTA
|
|
43
48
|
end
|
44
49
|
|
45
50
|
class DirectionsResponse < CTA::API::Response
|
51
|
+
# @return [Array<Direction>] An array of {Direction} that the requested route operates.
|
46
52
|
attr_reader :directions
|
47
53
|
|
48
54
|
def initialize(parsed_body, raw_body, debug)
|
@@ -52,6 +58,9 @@ module CTA
|
|
52
58
|
end
|
53
59
|
|
54
60
|
class StopsResponse < CTA::API::Response
|
61
|
+
# @return [Array<CTA::Stop>] An array with full {CTA::Stop} objects that correspond to the stops returned from the API.
|
62
|
+
# @note Some stops returned from BusTracker are not found in GTFS data, so cta_redux creates them on the fly. These
|
63
|
+
# stops are for seasonal routes. An email has been sent to the CTA asking why they're not included in the GTFS data (they should be).
|
55
64
|
attr_reader :stops
|
56
65
|
|
57
66
|
def initialize(parsed_body, raw_body, debug)
|
@@ -63,6 +72,7 @@ module CTA
|
|
63
72
|
end
|
64
73
|
|
65
74
|
class PatternsResponse < CTA::API::Response
|
75
|
+
# @return [Array<Pattern>] An array of {Pattern} objects for the requested query.
|
66
76
|
attr_reader :patterns
|
67
77
|
|
68
78
|
def initialize(parsed_body, raw_body, debug)
|
@@ -72,22 +82,28 @@ module CTA
|
|
72
82
|
end
|
73
83
|
|
74
84
|
class PredictionsResponse < CTA::API::Response
|
85
|
+
# @return [Array<CTA::Bus>] An array of {CTA::Bus} objects that correspond to the predictions requested.
|
75
86
|
attr_reader :vehicles
|
87
|
+
# @return [Array<CTA::Bus::Prediction>] An array of {CTA::Bus::Prediction} objects that correspond to the predictions requested.
|
88
|
+
# This is equivalent to calling +vehicles.map { |b| b.live.predictions }.flatten+
|
76
89
|
attr_reader :predictions
|
77
90
|
|
78
91
|
def initialize(parsed_body, raw_body, debug)
|
79
92
|
super(parsed_body, raw_body, debug)
|
80
93
|
@vehicles = Array.wrap(parsed_body["bustime_response"]["prd"]).map do |p|
|
81
94
|
bus = CTA::Bus.find_active_run(p["rt"], p["tmstmp"], (p["dly"] == "true")).first
|
82
|
-
bus.live
|
95
|
+
bus.live = CTA::Bus::Live.new(p, p)
|
83
96
|
|
84
97
|
bus
|
85
98
|
end
|
86
|
-
@predictions = @vehicles.map
|
99
|
+
@predictions = @vehicles.map { |b| b.live.predictions }.flatten
|
87
100
|
end
|
88
101
|
end
|
89
102
|
|
90
103
|
class ServiceBulletinsResponse < CTA::API::Response
|
104
|
+
# @return [Array<ServiceBulletin>] An array of {ServiceBulletin} objects that correspond to the query requested.
|
105
|
+
# @note Consider using the {CTA::CustomerAlerts} methods to search for alerts, as theoretically they should have the same
|
106
|
+
# data and it is not a rate-limited API.
|
91
107
|
attr_reader :bulletins
|
92
108
|
|
93
109
|
def initialize(parsed_body, raw_body, debug)
|
@@ -97,7 +113,19 @@ module CTA
|
|
97
113
|
end
|
98
114
|
|
99
115
|
class ServiceBulletin
|
100
|
-
|
116
|
+
# @return [String] The name of the bulletin.
|
117
|
+
attr_reader :name
|
118
|
+
# @return [String] A short description of the bulletin.
|
119
|
+
attr_reader :subject
|
120
|
+
# @return [String] More details about the bulletin
|
121
|
+
attr_reader :details
|
122
|
+
# @return [String] Another short description of the bulletin
|
123
|
+
# @note This seems to usually be unset by the CTA.
|
124
|
+
attr_reader :brief
|
125
|
+
# @return [Symbol] Priority of the alert. One of +[:low, :medium, :high]+
|
126
|
+
attr_reader :priority
|
127
|
+
# @return [Array<Service>] An array of {Service} objects that encapsulate information (if any) about which routes and stops are affected by this bulletin.
|
128
|
+
attr_reader :affected_services
|
101
129
|
|
102
130
|
def initialize(sb)
|
103
131
|
@name = sb["nm"]
|
@@ -111,9 +139,16 @@ module CTA
|
|
111
139
|
end
|
112
140
|
|
113
141
|
class Service
|
142
|
+
# @return [CTA::Route] A {CTA::Route}, if any, affected by a {ServiceBulletin}
|
114
143
|
attr_reader :route
|
144
|
+
# @return [Direction] A {Direction} object for the direction, if any, affected by a {ServiceBulletin}
|
115
145
|
attr_reader :direction
|
146
|
+
# @return [CTA::Stop] A specific {CTA::Stop} object for the stop affected by a {ServiceBulletin}
|
116
147
|
attr_reader :stop
|
148
|
+
|
149
|
+
# @return [String] The name of the {CTA::Stop} affected.
|
150
|
+
# @note Usually this is equivalent to calling +stop.name+, but sometimes the CTA returns a {ServiceBulletin} with a stop name,
|
151
|
+
# but no stop id set - and the stop name may not exactly correspond to a {CTA::Stop} object in the GTFS feed.
|
117
152
|
attr_reader :stop_name
|
118
153
|
|
119
154
|
def initialize(s)
|
@@ -134,11 +169,22 @@ module CTA
|
|
134
169
|
end
|
135
170
|
end
|
136
171
|
|
172
|
+
# @note {Pattern} objects enclose {Point} objects that describe a bus route. Conceptually it is similar to how a {CTA::Trip} contains
|
173
|
+
# many {CTA::StopTime} objects that describe the route a vehicle takes. However, it is specific to busses and contains better information
|
174
|
+
# for drawing turns and side-streets that the bus may take on its route. This bit of the API is mostly unnecessary unless you're drawing
|
175
|
+
# maps.
|
137
176
|
class Pattern
|
177
|
+
# @return [Integer] The ID of the pattern
|
138
178
|
attr_reader :id
|
179
|
+
# @return [Integer] The ID of the pattern
|
139
180
|
attr_reader :pattern_id
|
181
|
+
# @return [Integer] The total length of the pattern
|
140
182
|
attr_reader :length
|
183
|
+
# @return [Direction] A {Direction} object that describes to which direction of a route this pattern applies.
|
184
|
+
# @note This logically means that any given bus route (so long as it's not a circulator or one-way express) will have
|
185
|
+
# two associated {Pattern} objects
|
141
186
|
attr_reader :direction
|
187
|
+
# @return [Array<Point>] An array of {Point} objects that describe stops and waypoints along the {Pattern}
|
142
188
|
attr_reader :points
|
143
189
|
|
144
190
|
def initialize(p)
|
@@ -151,7 +197,22 @@ module CTA
|
|
151
197
|
end
|
152
198
|
|
153
199
|
class Point
|
154
|
-
|
200
|
+
# @return [Integer] The order that this {Point} appears along a {Pattern}
|
201
|
+
attr_reader :sequence
|
202
|
+
# @return [Float] The latitude of this {Point}
|
203
|
+
attr_reader :lat
|
204
|
+
# @return [Float] The longitude of this {Point}
|
205
|
+
attr_reader :lon
|
206
|
+
# @return [Float] The latitude of this {Point}
|
207
|
+
attr_reader :latitude
|
208
|
+
# @return [Float] The longitude of this {Point}
|
209
|
+
attr_reader :longitude
|
210
|
+
# @return [Symbol] The type of this {Point}. One of +[:stop, :waypoint]+
|
211
|
+
attr_reader :type
|
212
|
+
# @return [CTA::Stop] The {CTA::Stop} associated with this point.
|
213
|
+
attr_reader :stop
|
214
|
+
# @return [Float] The physical distance into a {Pattern} that corresponds to this {Point}
|
215
|
+
attr_reader :distance
|
155
216
|
|
156
217
|
def initialize(p)
|
157
218
|
@sequence = p["seq"].to_i
|
@@ -168,6 +229,9 @@ module CTA
|
|
168
229
|
end
|
169
230
|
|
170
231
|
class Direction
|
232
|
+
# @return [String] A direction for a service.
|
233
|
+
# @note The raw BusTracker API expects directions in the exact format this object returns. This is mostly an implementation detail, but
|
234
|
+
# explains a bit about why this object even exists.
|
171
235
|
attr_reader :direction
|
172
236
|
|
173
237
|
def initialize(d)
|
@@ -5,7 +5,16 @@ require 'multi_xml'
|
|
5
5
|
module CTA
|
6
6
|
class CustomerAlerts
|
7
7
|
class RouteStatus
|
8
|
-
|
8
|
+
# @return [CTA::Route] The {CTA::Route} that corresponds to this {RouteStatus}
|
9
|
+
attr_reader :route
|
10
|
+
# @return [String] The color the CTA suggests when displaying information about this alert.
|
11
|
+
attr_reader :route_color
|
12
|
+
# @return [String] The color of text the CTA suggests when displaying information about this alert.
|
13
|
+
attr_reader :route_text_color
|
14
|
+
# @return [String] A text description of the status of this route.
|
15
|
+
attr_reader :status
|
16
|
+
# @return [String] A color suggestion from the CTA when displaying information about the route status.
|
17
|
+
attr_reader :status_color
|
9
18
|
|
10
19
|
def initialize(s)
|
11
20
|
@route = CTA::Route.where(:route_id => s["Route"].split(" ").first).or(:route_id => s["ServiceId"]).first
|
@@ -17,9 +26,40 @@ module CTA
|
|
17
26
|
end
|
18
27
|
|
19
28
|
class Alert
|
20
|
-
|
21
|
-
|
22
|
-
|
29
|
+
# @return [Integer] The internal ID of this alert
|
30
|
+
attr_reader :id
|
31
|
+
# @return [Integer] The internal ID of this alert
|
32
|
+
attr_reader :alert_id
|
33
|
+
# @return [String] A descriptive one-line summary for this alert
|
34
|
+
attr_reader :headline
|
35
|
+
# @return [String] A descriptive short summary for this alert
|
36
|
+
attr_reader :short_description
|
37
|
+
# @return [String] A long-form summary for this alert.
|
38
|
+
# @note HTML formatted.
|
39
|
+
attr_reader :full_description
|
40
|
+
# @return [0..99] A score that describes how an impact this alert will have on any affected services.
|
41
|
+
# @note The score ranges from +0-99+. It's unclear how this is calculated internally, but higher numbers seem to be worse.
|
42
|
+
attr_reader :score
|
43
|
+
# @return [String] The hex color used to color text related to this alert on transitchicago.com
|
44
|
+
attr_reader :severity_color
|
45
|
+
# @return [Symbol] One of +[:normal, :planned, :major, :minor]+
|
46
|
+
attr_reader :category
|
47
|
+
# @return [String] Descriptive text detailing the impact of this alert.
|
48
|
+
attr_reader :impact
|
49
|
+
# @return [DateTime] The date and time at which this alert takes effect.
|
50
|
+
attr_reader :start
|
51
|
+
# @return [DateTime] The date and time at which this alert ends. May be unknown.
|
52
|
+
attr_reader :end
|
53
|
+
# @return [true,false] Returns true if the alert is 'TBD' - that is, the end time is unknown.
|
54
|
+
attr_reader :tbd
|
55
|
+
# @return [true,false] Returns true if the alert is 'major' - that is the CTA is displaying it prominently on transitchicago.com and expects it to cause major headaches.
|
56
|
+
attr_reader :major_alert
|
57
|
+
# @return [true,false] Returns true if the alert is 'major' - that is the CTA is displaying it prominently on transitchicago.com and expects it to cause major headaches.
|
58
|
+
attr_reader :is_major_alert
|
59
|
+
# @return [String] A URL where customers could learn more about the alert.
|
60
|
+
attr_reader :url
|
61
|
+
# @return [Array<CTA::Route>] An array of {CTA::Route} objects that are impacted by this alert.
|
62
|
+
attr_reader :services
|
23
63
|
|
24
64
|
def initialize(a)
|
25
65
|
@id = @alert_id = a["AlertId"].to_i
|
@@ -41,12 +81,14 @@ module CTA
|
|
41
81
|
end
|
42
82
|
end
|
43
83
|
|
84
|
+
# @return [true,false] Returns true if the alert is 'major' - that is the CTA is displaying it prominently on transitchicago.com and expects it to cause major headaches.
|
44
85
|
def major?
|
45
86
|
@major_alert
|
46
87
|
end
|
47
88
|
end
|
48
89
|
|
49
90
|
class AlertsResponse < CTA::API::Response
|
91
|
+
# @return [Array<Alert>] An array of {Alert} objects that match the requested query.
|
50
92
|
attr_reader :alerts
|
51
93
|
|
52
94
|
def initialize(parsed_body, raw_body, debug)
|
@@ -56,6 +98,7 @@ module CTA
|
|
56
98
|
end
|
57
99
|
|
58
100
|
class RouteStatusResponse < CTA::API::Response
|
101
|
+
# @return [Array<RouteStatus>] An array of {RouteStatus} objects that match the requested query.
|
59
102
|
attr_reader :routes
|
60
103
|
|
61
104
|
def initialize(parsed_body, raw_body, debug)
|
@@ -1,7 +1,14 @@
|
|
1
1
|
module CTA
|
2
2
|
class TrainTracker
|
3
3
|
class ArrivalsResponse < CTA::API::Response
|
4
|
-
|
4
|
+
# @return [Array<CTA::Route>] An array of {CTA::Route} objects that correspond to the predictions requested.
|
5
|
+
attr_reader :routes
|
6
|
+
# @return [Array<CTA::Train>] An array of {CTA::Train} objects that correspond to the predictions requested.
|
7
|
+
# @note Convenience method, equivalent to calling +routes.map { |r| r.vehicles }.flatten+
|
8
|
+
attr_reader :trains
|
9
|
+
# @return [Array<CTA::Train::Prediction>] An array of {CTA::Train::Prediction} objects that correspond to the predictions requested.
|
10
|
+
# @note Convenience method, equivalent to calling +trains.map { |t| t.live.predictions }.flatten+
|
11
|
+
attr_reader :predictions
|
5
12
|
|
6
13
|
def initialize(parsed_body, raw_body, debug)
|
7
14
|
super(parsed_body, raw_body, debug)
|
@@ -20,24 +27,28 @@ module CTA
|
|
20
27
|
train = CTA::Train.find_active_run(t["rn"], self.timestamp, true).first
|
21
28
|
end
|
22
29
|
position = t.select { |k,v| ["lat", "lon", "heading"].include?(k) }
|
23
|
-
train.live
|
30
|
+
train.live = CTA::Train::Live.new(position, t)
|
24
31
|
|
25
32
|
train
|
26
33
|
end
|
27
34
|
|
28
35
|
route = CTA::Route.where(:route_id => rt.capitalize).first
|
29
|
-
route.live
|
36
|
+
route.live = CTA::Route::Live.new(trains)
|
30
37
|
|
31
38
|
route
|
32
39
|
end
|
33
40
|
|
34
|
-
@trains = @routes.map
|
35
|
-
@predictions = @trains.map
|
41
|
+
@trains = @routes.map { |r| r.live.vehicles }.flatten
|
42
|
+
@predictions = @trains.map { |t| t.live.predictions }.flatten
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
39
46
|
class FollowResponse < CTA::API::Response
|
40
|
-
|
47
|
+
# @return [CTA::Train] The {CTA::Train} that corresponds to the train for which you've requested follow predictions.
|
48
|
+
attr_reader :train
|
49
|
+
# @return [Array<CTA::Train::Prediction>] An array of {CTA::Train::Prediction} objects that correspond to the predictions requested.
|
50
|
+
# @note Convenience method, equivalent to calling +train.map { |t| t.live.predictions }.flatten+
|
51
|
+
attr_reader :predictions
|
41
52
|
|
42
53
|
def initialize(parsed_body, raw_body, debug)
|
43
54
|
super(parsed_body, raw_body, debug)
|
@@ -47,13 +58,20 @@ module CTA
|
|
47
58
|
if !@train
|
48
59
|
@train = CTA::Train.find_active_run(train_info["rn"], self.timestamp, true).first
|
49
60
|
end
|
50
|
-
@train.live
|
51
|
-
@predictions = @train.predictions
|
61
|
+
@train.live = CTA::Train::Live.new(parsed_body["ctatt"]["position"], parsed_body["ctatt"]["eta"])
|
62
|
+
@predictions = @train.live.predictions
|
52
63
|
end
|
53
64
|
end
|
54
65
|
|
55
66
|
class PositionsResponse < CTA::API::Response
|
56
|
-
|
67
|
+
# @return [Array<CTA::Route>] An array of {CTA::Route} objects that correspond to the positions requested.
|
68
|
+
attr_reader :routes
|
69
|
+
# @return [Array<CTA::Train>] An array of {CTA::Train} objects that correspond to the positions requested.
|
70
|
+
# @note Convenience method, equivalent to calling +routes.compact.map { |r| r.live.vehicles }.flatten+
|
71
|
+
attr_reader :trains
|
72
|
+
# @return [Array<CTA::Train::Prediction>] An array of {CTA::Train::Prediction} objects that correspond to the positions requested.
|
73
|
+
# @note Convenience method, equivalent to calling +trains.map { |t| t.live.predictions }.flatten+
|
74
|
+
attr_reader :predictions
|
57
75
|
|
58
76
|
def initialize(parsed_body, raw_body, debug)
|
59
77
|
super(parsed_body, raw_body, debug)
|
@@ -72,17 +90,17 @@ module CTA
|
|
72
90
|
end
|
73
91
|
|
74
92
|
position = train.select { |k,v| ["lat", "lon", "heading"].include?(k) }
|
75
|
-
t.live
|
93
|
+
t.live = CTA::Train::Live.new(position, train)
|
76
94
|
|
77
95
|
t
|
78
96
|
end
|
79
97
|
|
80
|
-
rt.live
|
98
|
+
rt.live = CTA::Route::Live.new(trains)
|
81
99
|
rt
|
82
100
|
end.compact
|
83
101
|
|
84
|
-
@trains = @routes.compact.map
|
85
|
-
@predictions = @trains.compact.map
|
102
|
+
@trains = @routes.compact.map { |r| r.live.vehicles }.flatten
|
103
|
+
@predictions = @trains.compact.map { |t| t.live.predictions }.flatten
|
86
104
|
end
|
87
105
|
end
|
88
106
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module CTA
|
2
2
|
class BusTracker
|
3
|
+
@cache_responses = true
|
4
|
+
|
3
5
|
# Returns the connection object we use to talk to the BusTracker API
|
4
6
|
def self.connection
|
5
7
|
raise "You need to set a developer key first. Try CTA::BusTracker.key = 'foo'." unless @key
|
@@ -9,7 +11,9 @@ module CTA
|
|
9
11
|
faraday.params = { :key => @key }
|
10
12
|
|
11
13
|
faraday.use CTA::BusTracker::Parser, !!@debug
|
12
|
-
|
14
|
+
if @cache_responses
|
15
|
+
faraday.response :caching, (@cache || SimpleCache.new(Hash.new))
|
16
|
+
end
|
13
17
|
faraday.adapter Faraday.default_adapter
|
14
18
|
end
|
15
19
|
end
|
@@ -80,7 +84,7 @@ module CTA
|
|
80
84
|
end
|
81
85
|
|
82
86
|
# Returns the stops along a route and direction
|
83
|
-
# @
|
87
|
+
# @param [Hash] options
|
84
88
|
# @option options [String, Integer] :route The route to query for stops
|
85
89
|
# @option options [String, Integer] :direction The direction to query for stops
|
86
90
|
# @return [CTA::BusTracker::StopsResponse]
|
@@ -113,7 +117,7 @@ module CTA
|
|
113
117
|
end
|
114
118
|
|
115
119
|
# Returns available patterns for a route
|
116
|
-
# @
|
120
|
+
# @param [Hash] options
|
117
121
|
# @option options [String, Integer] :route The route to query for patterns. Not available with :patterns
|
118
122
|
# @option options [Array<String>, Array<Integer>, String, Integer] :patterns Patterns to return. Not available with :route
|
119
123
|
# @return [CTA::BusTracker::PatternsResponse]
|
@@ -143,7 +147,7 @@ module CTA
|
|
143
147
|
end
|
144
148
|
|
145
149
|
# Returns a set of arrival/departure predictions.
|
146
|
-
# @
|
150
|
+
# @param [Hash] options
|
147
151
|
# @option options [Array<String>, Array<Integer>, String, Integer] :vehicles Vehicles to predict. Not available with :routes
|
148
152
|
# @option options [Array<String>, Array<Integer>, String, Integer] :routes Routes to predict. Not available with :vehicles
|
149
153
|
# @option options [Array<String>, Array<Integer>, String, Integer] :stops Stops along a route to predict. Required with :routes
|
@@ -175,7 +179,7 @@ module CTA
|
|
175
179
|
|
176
180
|
# Returns active bulletins.
|
177
181
|
# @note Consider using {CTA::CustomerAlerts.alerts!} or {CTA::CustomerAlerts.status!}, as those are not rate-limited.
|
178
|
-
# @
|
182
|
+
# @param [Hash] options
|
179
183
|
# @option options [Array<String>, Array<Integer>, String, Integer] :routes Routes for which to retrieve bulletins.
|
180
184
|
# When combined with :direction or :stops, may only specify one :route.
|
181
185
|
# @option options [String, Integer] :direction Direction of a route for which to retrieve bulletins.
|
@@ -245,5 +249,38 @@ module CTA
|
|
245
249
|
@debug = debug
|
246
250
|
@connection = nil
|
247
251
|
end
|
252
|
+
|
253
|
+
# Returns whether or not cta_redux is caching responses
|
254
|
+
# @return [true, false]
|
255
|
+
def self.cache_responses
|
256
|
+
@cache_responses
|
257
|
+
end
|
258
|
+
|
259
|
+
# Sets whether or not cta_redux is caching responses
|
260
|
+
# @param [true, false] should_cache
|
261
|
+
def self.cache_responses=(should_cache)
|
262
|
+
@cache_responses = should_cache
|
263
|
+
@connection = nil
|
264
|
+
end
|
265
|
+
|
266
|
+
# Returns the underlying cache object caching responses (if we're actually caching responses)
|
267
|
+
# @return [Object]
|
268
|
+
def self.cache
|
269
|
+
if self.cache_responses
|
270
|
+
# This is ugly
|
271
|
+
@cache || self.connection.builder.handlers.find { |x| x == FaradayMiddleware::Caching }.instance_variable_get(:@args).first
|
272
|
+
else
|
273
|
+
nil
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# Sets the underlying cache object caching responses. Any object can be used that responds to #read, #write, and #fetch
|
278
|
+
# @note Setting the cache object resets the connection. If you're using the default SimpleCache strategy (built-in 60
|
279
|
+
# second caching), then it will also *clear* the cache.
|
280
|
+
# @param [Object] cache
|
281
|
+
def self.cache=(cache)
|
282
|
+
@cache = cache
|
283
|
+
@connection = nil
|
284
|
+
end
|
248
285
|
end
|
249
286
|
end
|