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.
@@ -1,12 +1,15 @@
1
1
  module CTA
2
2
  class CustomerAlerts
3
+ @cache_responses = true
3
4
 
4
5
  # Returns the connection object we use to talk to the CustomerAlerts API
5
6
  def self.connection
6
7
  @connection ||= Faraday.new do |faraday|
7
8
  faraday.url_prefix = 'http://www.transitchicago.com/api/1.0/'
8
9
  faraday.use CTA::CustomerAlerts::Parser, !!@debug
9
- faraday.response :caching, SimpleCache.new(Hash.new)
10
+ if @cache_responses
11
+ faraday.response :caching, (@cache || SimpleCache.new(Hash.new))
12
+ end
10
13
  faraday.adapter Faraday.default_adapter
11
14
  end
12
15
  end
@@ -93,5 +96,38 @@ module CTA
93
96
  @debug = debug
94
97
  @connection = nil
95
98
  end
99
+
100
+ # Returns whether or not cta_redux is caching responses
101
+ # @return [true, false]
102
+ def self.cache_responses
103
+ @cache_responses
104
+ end
105
+
106
+ # Sets whether or not cta_redux is caching responses
107
+ # @param [true, false] should_cache
108
+ def self.cache_responses=(should_cache)
109
+ @cache_responses = should_cache
110
+ @connection = nil
111
+ end
112
+
113
+ # Returns the underlying cache object caching responses (if we're actually caching responses)
114
+ # @return [Object]
115
+ def self.cache
116
+ if self.cache_responses
117
+ # This is ugly
118
+ @cache || self.connection.builder.handlers.find { |x| x == FaradayMiddleware::Caching }.instance_variable_get(:@args).first
119
+ else
120
+ nil
121
+ end
122
+ end
123
+
124
+ # Sets the underlying cache object caching responses. Any object can be used that responds to #read, #write, and #fetch
125
+ # @note Setting the cache object resets the connection. If you're using the default SimpleCache strategy (built-in 60
126
+ # second caching), then it will also *clear* the cache.
127
+ # @param [Object] cache
128
+ def self.cache=(cache)
129
+ @cache = cache
130
+ @connection = nil
131
+ end
96
132
  end
97
133
  end
@@ -1,3 +1,5 @@
1
+ # A simplistic in-process cache.
2
+ # Used internally by cta_redux and caches responses for 60 seconds.
1
3
  class SimpleCache
2
4
  def initialize(cache)
3
5
  @cache = cache
@@ -1,4 +1,26 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#agency_txt___Field_Definitions agency.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:agency_name, :agency_url, :agency_timezone, :agency_lang, :agency_phone, :agency_fare_url]
2
6
  class Agency < Sequel::Model(:agency)
7
+ # @!method agency_name
8
+ # @return [String]
9
+ # @!method agency_url
10
+ # @return [String]
11
+ # @!method agency_timezone
12
+ # @return [String]
13
+ # @!method agency_lang
14
+ # @return [String]
15
+ # @!method agency_phone
16
+ # @return [String]
17
+ # @!method agency_fare_url
18
+ # @return [String]
19
+ alias_method :name, :agency_name
20
+ alias_method :url, :agency_url
21
+ alias_method :timezone, :agency_timezone
22
+ alias_method :language, :agency_lang
23
+ alias_method :phone, :agency_phone
24
+ alias_method :fare_url, :agency_fare_url
3
25
  end
4
26
  end
@@ -1,32 +1,111 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}, inherited from {CTA::Trip}
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#trips_txt___Field_Definitions trips.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:route_id, :service_id, :trip_id, :direction_id, :block_id, :shape_id, :direction, :wheelchair_accessible, :schd_trip_id]
2
6
  class Bus < CTA::Trip
7
+ # @return [Live] the {Live} data associated with this {CTA::Bus}, if available.
8
+ # @note a {CTA::Bus} will only contain live data when augmented with an {API::Response}
9
+ attr_accessor :live
10
+
11
+ # @!method route_id
12
+ # @return [String]
13
+ # @!method service_id
14
+ # @return [Integer]
15
+ # @!method trip_id
16
+ # @return [Integer]
17
+ # @!method direction_id
18
+ # @return [Integer]
19
+ # @!method block_id
20
+ # @return [Integer]
21
+ # @!method shape_id
22
+ # @return [Integer]
23
+ # @!method direction
24
+ # @return [String]
25
+ # @!method wheelchair_accessible
26
+ # @return [true,false]
27
+ # @!method schd_trip_id
28
+ # @return [String]
29
+ alias_method :id, :route_id
30
+ alias_method :scheduled_trip_id, :schd_trip_id
31
+ alias_method :run, :schd_trip_id
32
+
33
+ # Returns predictions for this {CTA::Bus}. Accepts all options for {CTA::BusTracker.predictions!}, and will merge in
34
+ # it's own vehicle_id or route_id if present.
35
+ # @param [Hash] options
36
+ # @option options [Array<String>, Array<Integer>, String, Integer] :vehicles Vehicles to predict. Not available with :routes
37
+ # @option options [Array<String>, Array<Integer>, String, Integer] :routes Routes to predict. Not available with :vehicles
38
+ # @option options [Array<String>, Array<Integer>, String, Integer] :stops Stops along a route to predict. Required with :routes
39
+ # @option options [String, Integer] :limit Maximum number of predictions to return.
40
+ # @return [CTA::BusTracker::PredictionsResponse]
41
+ # @example
42
+ # predictions!(:stops => 15895)
43
+ # predictions!(:limit => 1)
3
44
  def predictions!(options = {})
4
45
  opts = (self.vehicle_id ? { :vehicles => self.vehicle_id } : { :routes => self.route_id })
5
- puts opts
6
46
  CTA::BusTracker.predictions!(options.merge(opts))
7
47
  end
8
48
 
9
- def live!(position, predictions = [])
10
- class << self
11
- attr_reader :lat, :lon, :vehicle_id, :heading, :pattern_id, :pattern_distance, :route, :delayed, :speed, :predictions
12
- end
49
+ class Live
50
+ # @return [Float] The latitude of the {CTA::Bus}.
51
+ attr_reader :lat
52
+ # @return [Float] The longitude of the {CTA::Bus}.
53
+ attr_reader :lon
54
+ # @return [Integer] The vehicle_id of the {CTA::Bus}.
55
+ attr_reader :vehicle_id
56
+ # @return [Integer] The heading of the {CTA::Bus}.
57
+ attr_reader :heading
58
+ # @return [Integer] The pattern the {CTA::Bus} is following.
59
+ attr_reader :pattern_id
60
+ # @return [Integer] The distance into the pattern the {CTA::Bus} is following.
61
+ attr_reader :pattern_distance
62
+ # @return [CTA::Route] The {CTA::Route} the {CTA::Bus} is operating.
63
+ attr_reader :route
64
+ # @return [true,false] True if the {CTA::Bus} is considered to be delayed.
65
+ attr_reader :delayed
66
+ # @return [Integer] Last reported speed of the {CTA::Bus}, in mph.
67
+ attr_reader :speed
68
+ # @return [Array<Prediction>] Predictions for this {CTA::Bus}.
69
+ attr_reader :predictions
13
70
 
14
- @lat = position["lat"].to_f
15
- @lon = position["lon"].to_f
16
- @heading = position["hdg"].to_i
17
- @vehicle_id = position["vid"].to_i
18
- @pattern_id = position["pid"].to_i
19
- @pattern_distance = position["pdist"].to_i
20
- @route = CTA::Route.where(:route_id => position["rt"]).first
21
- @delayed = (position["dly"] == "true")
22
- @speed = position["spd"].to_i
71
+ def initialize(position, predictions = [])
72
+ @lat = position["lat"].to_f
73
+ @lon = position["lon"].to_f
74
+ @heading = position["hdg"].to_i
75
+ @vehicle_id = position["vid"].to_i
76
+ @pattern_id = position["pid"].to_i
77
+ @pattern_distance = position["pdist"].to_i
78
+ @route = CTA::Route.where(:route_id => position["rt"]).first
79
+ @delayed = (position["dly"] == "true")
80
+ @speed = position["spd"].to_i
23
81
 
24
- @predictions = Array.wrap(predictions).map { |p| Prediction.new(p) }
82
+ @predictions = Array.wrap(predictions).map { |p| Prediction.new(p) }
83
+ end
25
84
  end
26
85
 
27
86
  class Prediction
28
- attr_reader :type, :stop, :distance, :route, :direction, :destination,
29
- :prediction_generated_at, :arrival_time, :delayed, :minutes, :seconds
87
+ # @return [String] The type of prediction, either *A*rrival or *D*eparture
88
+ attr_reader :type
89
+ # @return [CTA::Stop] The {CTA::Stop} for this prediction
90
+ attr_reader :stop
91
+ # @return [Integer] The distance remaining until the bus arrives
92
+ attr_reader :distance
93
+ # @return [CTA::Route] The {CTA::Route} associated with this prediction
94
+ attr_reader :route
95
+ # @return [Direction] The {Direction} associated with this prediction
96
+ attr_reader :direction
97
+ # @return [String] The headsign of the bus (final destination, *not* expressed as {CTA::Stop})
98
+ attr_reader :headsign
99
+ # @return [DateTime] The time this {Prediction} was generated on the BusTime servers
100
+ attr_reader :prediction_generated_at
101
+ # @return [DateTime] The time this bus is predicted to arrive or depart
102
+ attr_reader :arrival_time
103
+ # @return [true, false] True if this bus is considered to be delayed
104
+ attr_reader :delayed
105
+ # @return [Integer] The number of minutes until this bus arrives or departs
106
+ attr_reader :minutes
107
+ # @return [Integer] The number of seconds until this bus arrives or departs
108
+ attr_reader :seconds
30
109
 
31
110
  def initialize(data)
32
111
  @type = data["typ"]
@@ -34,7 +113,7 @@ module CTA
34
113
  @distance = data["dstp"].to_i
35
114
  @route = CTA::Route.where(:route_id => data["rt"]).first
36
115
  @direction = CTA::BusTracker::Direction.new(data["rtdir"])
37
- @destination = data["des"]
116
+ @headsign = data["des"]
38
117
  @prediction_generated_at = DateTime.parse(data["tmstmp"])
39
118
  @arrival_time = DateTime.parse(data["prdtm"])
40
119
  @seconds = @arrival_time.to_time - @prediction_generated_at.to_time
@@ -1,7 +1,35 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#calendar_txt___Field_Definitions calendar.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:service_id, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday, :start_date, :end_date]
2
6
  class Calendar < Sequel::Model(:calendar)
3
7
  set_primary_key :service_id
4
8
 
9
+ # @!method service_id
10
+ # @return [String]
11
+ # @!method monday
12
+ # @return [true,false]
13
+ # @!method tuesday
14
+ # @return [true,false]
15
+ # @!method wednesday
16
+ # @return [true,false]
17
+ # @!method thursday
18
+ # @return [true,false]
19
+ # @!method friday
20
+ # @return [true,false]
21
+ # @!method saturday
22
+ # @return [true,false]
23
+ # @!method sunday
24
+ # @return [true,false]
25
+ # @!method start_date
26
+ # @return [Date]
27
+ # @!method end_date
28
+ # @return [Date]
29
+
30
+ # @!method trips
31
+ # A {CTA::Calendar} defines a time period during which multiple {CTA::Trip}s may or may not be active.
32
+ # @return [Array<CTA::Trip>] All trips associated with this service
5
33
  one_to_many :trips, :key => :service_id
6
34
  end
7
35
  end
@@ -1,9 +1,50 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#routes_txt___Field_Definitions routes.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:route_id, :route_short_name, :route_long_name, :route_type, :route_url, :route_color, :route_text_color]
2
6
  class Route < Sequel::Model
7
+ # @return [Live] the {Live} data associated with this {CTA::Route}, if available.
8
+ # @note a {CTA::Route} will only contain live data when augmented with an {API::Response}
9
+ attr_accessor :live
3
10
  set_primary_key :route_id
4
11
 
12
+ # @!method trips
13
+ # A {CTA::Route} may be associated with multiple trips ("runs").
14
+ # @return [Array<CTA::Trip>] All trips associated with this route
5
15
  one_to_many :trips, :key => :route_id
6
16
 
17
+ # @!method route_id
18
+ # @return [String]
19
+ # @!method route_short_name
20
+ # @return [String]
21
+ # @!method route_long_name
22
+ # @return [String]
23
+ # @!method route_type
24
+ # @return [Integer]
25
+ # @!method route_url
26
+ # @return [String]
27
+ # @!method route_color
28
+ # @return [String]
29
+ # @!method route_text_color
30
+ # @return [String]
31
+ alias_method :id, :route_id
32
+ alias_method :name, :route_short_name
33
+ alias_method :short_name, :route_short_name
34
+ alias_method :long_name, :route_long_name
35
+ alias_method :type, :route_type
36
+ alias_method :url, :route_url
37
+ alias_method :color, :route_color
38
+ alias_method :text_color, :route_text_color
39
+
40
+ # Overrides the default "find by primary key" method in {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
41
+ # Allows you to specify a human-friendly {CTA::Train} name. If you supply something that doesn't look like an "L" route, it's passed
42
+ # to the default [] method on Sequel::Model.
43
+ # @return [CTA::Route] The route requested
44
+ # @example
45
+ # CTA::Route[:brown] #=> equivalent to calling CTA::Route["Brn"]
46
+ # CTA::Route["Brown"] #=> equivalent to calling CTA::Route["Brn"]
47
+ # CTA::Route["8"] #=> equivalent to calling CTA::Route["8"]
7
48
  def self.[](*args)
8
49
  potential_route = args.first.downcase.to_sym
9
50
  if CTA::Train::FRIENDLY_L_ROUTES.has_key?(potential_route)
@@ -13,8 +54,13 @@ module CTA
13
54
  end
14
55
  end
15
56
 
57
+ # Returns a {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Dataset.html Sequel::Dataset} that corresponds to stops associated
58
+ # with this {CTA::Route}
59
+ # @return [Sequel::Dataset]
60
+ # @example
61
+ # CTA::Route["brown"].stops.first #=> #<CTA::Stop...
62
+ # CTA::Route["brown"].stops.all #=> [#<CTA::Stop..., #<CTA::Stop...]
16
63
  def stops
17
- # Gosh, I wish SQLite could do "SELECT DISTINCT ON..."
18
64
  CTA::Stop.with_sql(<<-SQL)
19
65
  SELECT s.*
20
66
  FROM stops s
@@ -27,14 +73,9 @@ module CTA
27
73
  SQL
28
74
  end
29
75
 
30
- def live!(vehicles)
31
- class << self
32
- attr_reader :vehicles
33
- end
34
-
35
- @vehicles = vehicles
36
- end
37
-
76
+ # Returns predictions for this specific {CTA::Route}. Accepts all optiosn of either
77
+ # {CTA::BusTracker.predictions!} or {CTA::TrainTracker.predictions!}, depending on the type of this {CTA::Route}
78
+ # @return [CTA::BusTracker::PredictionsResponse, CTA::TrainTracker::ArrivalsResponse]
38
79
  def predictions!(options = {})
39
80
  if CTA::Train::L_ROUTES.keys.include?(self.route_id.downcase)
40
81
  CTA::TrainTracker.predictions!(options.merge({:route => self.route_id.downcase}))
@@ -43,6 +84,14 @@ module CTA
43
84
  end
44
85
  end
45
86
 
87
+ # Returns the position and next station of all trains in service for this route.
88
+ # @note Raises an exception when called on a {CTA::Bus} route, because the BusTracker API has nothing like the
89
+ # TrainTracker locations call
90
+ # @param [Hash] options
91
+ # @option options [Array<String>, Array<Integer>, String, Integer] :routes Routes for which to return positions
92
+ # @return [CTA::TrainTracker::LocationsResponse]
93
+ # @example
94
+ # locations!(:route => [:red, :blue])
46
95
  def locations!(options = {})
47
96
  if CTA::Train::L_ROUTES.keys.include?(self.route_id.downcase)
48
97
  CTA::TrainTracker.locations!(options.merge({:routes => self.route_id.downcase}))
@@ -51,12 +100,25 @@ module CTA
51
100
  end
52
101
  end
53
102
 
103
+ # Returns an overview of system status for this route
104
+ # @return [CTA::CustomerAlerts::RouteStatusResponse]
54
105
  def status!
55
106
  CTA::CustomerAlerts.status!(:routes => self.route_id).routes.first
56
107
  end
57
108
 
109
+ # Returns alerts for this route
110
+ # @return [CTA::CustomerAlerts::AlertsResponse]
58
111
  def alerts!
59
112
  CTA::CustomerAlerts.alerts!(:route => self.route_id).alerts
60
113
  end
114
+
115
+ class Live
116
+ # @return [Array<CTA::Bus>, Array<CTA::Train>] The live vehicles associated with this route
117
+ attr_reader :vehicles
118
+
119
+ def initialize(vehicles)
120
+ @vehicles = vehicles
121
+ end
122
+ end
61
123
  end
62
124
  end
@@ -1,4 +1,24 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#shapes_txt___Field_Definitions routes.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:shape_id, :shape_pt_lat, :shape_pt_lon, :shape_pt_sequence, :shape_dist_traveled]
2
6
  class Shape < Sequel::Model
7
+ # @!method shape_id
8
+ # @return [Integer]
9
+ # @!method shape_pt_lat
10
+ # @return [Float]
11
+ # @!method shape_pt_lon
12
+ # @return [Float]
13
+ # @!method shape_pt_sequence
14
+ # @return [Integer]
15
+ # @!method shape_dist_traveled
16
+ # @return [Integer]
17
+ alias_method :id, :shape_id
18
+ alias_method :lat, :shape_pt_lat
19
+ alias_method :lon, :shape_pt_lon
20
+ alias_method :sequence, :shape_pt_sequence
21
+ alias_method :distance, :shape_dist_traveled
22
+ alias_method :distance_traveled, :shape_dist_traveled
3
23
  end
4
24
  end
@@ -1,15 +1,71 @@
1
1
  module CTA
2
+ # A {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model.html Sequel::Model}.
3
+ # This corresponds to {https://developers.google.com/transit/gtfs/reference?csw=1#stops_txt___Field_Definitions stops.txt} in the
4
+ # GTFS feed, though the CTA does not fully implement the standard.
5
+ # @note Current columns: [:stop_id, :stop_code, :stop_name, :stop_desc, :stop_lat, :stop_lon, :location_type, :parent_station, :wheelchair_boarding]
2
6
  class Stop < Sequel::Model
3
7
  set_primary_key :stop_id
4
8
 
9
+ # @!method child_stops
10
+ # Stops can have a hierarchical relationship. The CTA designates certain stops as "parent stops" which contain "child stops"
11
+ # A great example of this is an 'L' station - the station itself will be a parent stop, but each platform will be a child stop.
12
+ # @return [Array<CTA::Stop>] Child {CTA::Stop}s of this stop
5
13
  one_to_many :child_stops, :class => self, :key => :parent_station
14
+ # @!method parent_stop
15
+ # Stops can have a hierarchical relationship. The CTA designates certain stops as "parent stops" which contain "child stops"
16
+ # A great example of this is an 'L' station - the station itself will be a parent stop, but each platform will be a child stop.
17
+ # @return [CTA::Stop] Parent {CTA::Stop} of this stop
6
18
  many_to_one :parent_stop, :class => self, :key => :parent_station
7
19
 
20
+ # @!method transfers_from
21
+ # GTFS defines a {CTA::Transfer} object, that describes where customers may transfer lines.
22
+ # This method defines which {CTA::Stop} customers may transfer *from* at this {CTA::Stop}.
23
+ # By then introspecting on {CTA::Route}s attached to these stops, you can find the transfer points between routes at this stop.
24
+ # @return [Array<CTA::Stop>] All {CTA::Stop}s from which a customer may transfer at this stop
8
25
  one_to_many :transfers_from, :class => 'CTA::Transfer', :key => :from_stop_id
26
+ # @!method transfers_to
27
+ # GTFS defines a {CTA::Transfer} object, that describes where customers may transfer lines.
28
+ # This method defines which {CTA::Stop} customers may transfer *to* at {CTA::Stop}.
29
+ # By then introspecting on {CTA::Route}s attached to these stops, you can find the transfer points between routes at this stop.
30
+ # @return [Array<CTA::Stop>] All {CTA::Stop}s to which a customer may transfer at this stop
9
31
  one_to_many :transfers_to, :class => 'CTA::Transfer', :key => :to_stop_id
10
32
 
33
+ # @!method trips
34
+ # A {CTA::Route} may be related to many trips, through {CTA::StopTime} objects
35
+ # @return [Array<CTA::Trip>] The trips that will at some point use this {CTA::Stop}
11
36
  many_to_many :trips, :left_key => :stop_id, :right_key => :trip_id, :join_table => :stop_times
12
37
 
38
+ # @!method stop_id
39
+ # @return [Integer]
40
+ # @!method stop_code
41
+ # @return [Integer]
42
+ # @!method stop_name
43
+ # @return [String]
44
+ # @!method stop_desc
45
+ # @return [String]
46
+ # @!method stop_lat
47
+ # @return [Float]
48
+ # @!method stop_lon
49
+ # @return [Float]
50
+ # @!method location_type
51
+ # @return [Integer]
52
+ # @!method parent_station
53
+ # @return [Integer]
54
+ # @!method wheelchair_boarding
55
+ # @return [true, false]
56
+ alias_method :id, :stop_id
57
+ alias_method :code, :stop_code
58
+ alias_method :name, :stop_name
59
+ alias_method :description, :stop_desc
60
+ alias_method :lat, :stop_lat
61
+ alias_method :lon, :stop_lon
62
+
63
+ # Returns a {http://sequel.jeremyevans.net/rdoc/classes/Sequel/Dataset.html Sequel::Dataset} that corresponds to all routes
64
+ # associated with this {CTA::Stop} at some point
65
+ # @return [Sequel::Dataset] All routes associated with this stop
66
+ # @example
67
+ # CTA::Stop.first.routes.first #=> #<CTA::Route...
68
+ # CTA::Stop.first.routes.all #=> [#<CTA::Route..., #<CTA::Route...]
13
69
  def routes
14
70
  CTA::Route.with_sql(<<-SQL)
15
71
  SELECT r.*
@@ -23,6 +79,7 @@ module CTA
23
79
  SQL
24
80
  end
25
81
 
82
+ # Internal method.
26
83
  # Some CTA routes are seasonal, and are missing from the GTFS feed.
27
84
  # However, the API still returns that info. So, we create a dummy CTA::Stop
28
85
  # to fill in the gaps. I've emailed CTA developer support for clarification.
@@ -41,6 +98,13 @@ module CTA
41
98
  stop
42
99
  end
43
100
 
101
+ # The type of this stop. CTA partitions all stops on the numeric stop_id. It's unclear why the CTA does this,
102
+ # but the TrainTracker API seems to separate out parent stations and stations in their requests, which complicates
103
+ # following the GTFS spec to the letter. Additionally, because GTFS has no concept of differentiating stops based
104
+ # on the type of vehicle expected to service that stop, the numerical ID can also differentiate a bus stop from a rail stop.
105
+ # Bottom line? The CTA's APIs and GTFS itself is really confusing, and the actual reasons why this method exists
106
+ # are unclear. You should just be able to rely on it.
107
+ # @return [:bus, :rail, :parent_station]
44
108
  def stop_type
45
109
  if self.stop_id < 30000
46
110
  :bus
@@ -51,6 +115,10 @@ module CTA
51
115
  end
52
116
  end
53
117
 
118
+ # Returns predictions for this {CTA::Stop}. Accepts all options for {CTA::BusTracker.predictions!} or {CTA::TrainTracker.predictions!},
119
+ # and will merge in # it's own stop/station/parent_station ID as needed.
120
+ # @params [Hash] options
121
+ # @return [CTA::BusTracker::PredictionsResponse, CTA::TrainTracker::ArrivalsResponse]
54
122
  def predictions!(options = {})
55
123
  if self.stop_type == :bus
56
124
  CTA::BusTracker.predictions!(options.merge({:stops => self.stop_id}))