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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e3939dcf2d580a8ef7487ea5f9ef1a3b1464737
4
- data.tar.gz: d148cd49ce17813bec6bed9b33fd3a0f4fe9393f
3
+ metadata.gz: f83f5bf3b8bfc681998bdaa39b19c45a77a8c388
4
+ data.tar.gz: 371f9733b0decd55ea6858f9e39b7cd8337a0ebe
5
5
  SHA512:
6
- metadata.gz: 1633690c5355c45aa87daafaf17fa261f25d495bd6b022b09394e9e067e5071c00e4b1293405ab015c9d88488b3ff1d272821c10a337bedd6f3ac2cc06742454
7
- data.tar.gz: 82df0c408f08a8c45def1be764730302620a9bfd70309d8ba4cd12617e72926c34b6f5b494a050639d25afa1d4aac739af078dd9c55ce3872de640df725f7437
6
+ metadata.gz: 996e04cc55d7f1d65aaa9703676aac5c818d1096b152f48a7d2aea9e2edc24a6aa8fed1c64cc4d2ceb6ca84de870c614ffa3b659707fd2533064f9deb5bcc016
7
+ data.tar.gz: 33b0201a8c53886c123e5ce98b22b0f3254b7af914044da8160821ce9f095162b632fce2c68ea377613d00452e150a5c89d31b2885b4a64ee4190e8a021248c9
@@ -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
@@ -37,4 +37,4 @@ CTA::CustomerAlerts.alerts!(:routes => routes.uniq).alerts.each do |alert|
37
37
  end
38
38
  ```
39
39
 
40
- More information is available at (http://www.rubydoc.info/gems/cta_redux/0.1.0)
40
+ More information is available at (http://www.rubydoc.info/github/ahayworth/cta_redux)
@@ -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!(v)
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!(p, p)
95
+ bus.live = CTA::Bus::Live.new(p, p)
83
96
 
84
97
  bus
85
98
  end
86
- @predictions = @vehicles.map(&:predictions).flatten
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
- attr_reader :name, :subject, :details, :brief, :priority, :affected_services
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
- attr_reader :sequence, :lat, :lon, :latitude, :longitude, :type, :stop, :distance
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
- attr_reader :route, :route_color, :route_text_color, :service_id, :route_url, :status, :status_color
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
- attr_reader :id, :alert_id, :headline, :short_description, :full_description, :score,
21
- :severity_color, :category, :impact, :start, :end, :tbd, :major_alert, :is_major_alert,
22
- :url, :services
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
- attr_reader :routes, :trains, :predictions
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!(position, t)
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!(trains)
36
+ route.live = CTA::Route::Live.new(trains)
30
37
 
31
38
  route
32
39
  end
33
40
 
34
- @trains = @routes.map(&:vehicles).flatten
35
- @predictions = @trains.map(&:predictions).flatten
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
- attr_reader :train, :predictions
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!(parsed_body["ctatt"]["position"], parsed_body["ctatt"]["eta"])
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
- attr_reader :routes, :trains, :predictions
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!(position, train)
93
+ t.live = CTA::Train::Live.new(position, train)
76
94
 
77
95
  t
78
96
  end
79
97
 
80
- rt.live!(trains)
98
+ rt.live = CTA::Route::Live.new(trains)
81
99
  rt
82
100
  end.compact
83
101
 
84
- @trains = @routes.compact.map(&:vehicles).flatten
85
- @predictions = @trains.compact.map(&:predictions).flatten
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
- faraday.response :caching, SimpleCache.new(Hash.new)
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
- # @params [Hash] options
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
- # @params [Hash] options
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
- # @params [Hash] options
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
- # @params [Hash] options
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