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
@@ -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
|
-
|
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,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
|
data/lib/cta_redux/models/bus.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
82
|
+
@predictions = Array.wrap(predictions).map { |p| Prediction.new(p) }
|
83
|
+
end
|
25
84
|
end
|
26
85
|
|
27
86
|
class Prediction
|
28
|
-
|
29
|
-
|
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
|
-
@
|
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
|
-
|
31
|
-
|
32
|
-
|
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}))
|