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