octranspo 0.0.0

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.
Files changed (73) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +26 -0
  4. data/Rakefile +8 -0
  5. data/lib/octranspo.rb +20 -0
  6. data/lib/octranspo/headsign.rb +2539 -0
  7. data/lib/octranspo/headsigns.yml +40565 -0
  8. data/lib/octranspo/landmarks.rb +37 -0
  9. data/lib/octranspo/lingo.rb +125 -0
  10. data/lib/octranspo/lingo/headsign_messages.yml +104 -0
  11. data/lib/octranspo/lingo/headsign_signatures.yml +3 -0
  12. data/lib/octranspo/lingo/landmarks.yml +205 -0
  13. data/lib/octranspo/lingo/roadways.yml +1957 -0
  14. data/lib/octranspo/mobile_resource_methods.rb +98 -0
  15. data/lib/octranspo/mobile_route_data.rb +85 -0
  16. data/lib/octranspo/mobile_route_schedule.rb +118 -0
  17. data/lib/octranspo/mobile_stop_schedule.rb +137 -0
  18. data/lib/octranspo/remote_resource_methods.rb +89 -0
  19. data/lib/octranspo/route.rb +31 -0
  20. data/lib/octranspo/routes.yml +507 -0
  21. data/lib/octranspo/service_date.rb +17 -0
  22. data/lib/octranspo/stations.yml +77 -0
  23. data/lib/octranspo/stop.rb +69 -0
  24. data/lib/octranspo/stop_resource.rb +46 -0
  25. data/lib/octranspo/stops.yml +30696 -0
  26. data/lib/octranspo/version.rb +3 -0
  27. data/octranspo.gemspec +22 -0
  28. data/test/fixtures/mobile_route_data/20090323/route_123_index_0.html +457 -0
  29. data/test/fixtures/mobile_route_data/20090323/route_123_index_1.html +99 -0
  30. data/test/fixtures/mobile_route_data/20090323/route_1_index_0.html +700 -0
  31. data/test/fixtures/mobile_route_data/20090323/route_1_index_1.html +691 -0
  32. data/test/fixtures/mobile_route_data/20090323/route_2_index_0.html +682 -0
  33. data/test/fixtures/mobile_route_data/20090323/route_2_index_1.html +646 -0
  34. data/test/fixtures/mobile_route_data/20100323/route_123_index_0.html +469 -0
  35. data/test/fixtures/mobile_route_data/20100323/route_123_index_1.html +105 -0
  36. data/test/fixtures/mobile_route_data/20100323/route_1_index_0.html +703 -0
  37. data/test/fixtures/mobile_route_data/20100323/route_1_index_1.html +694 -0
  38. data/test/fixtures/mobile_route_data/20100323/route_2_index_0.html +685 -0
  39. data/test/fixtures/mobile_route_data/20100323/route_2_index_1.html +649 -0
  40. data/test/fixtures/mobile_route_data/20100323/route_3_index_0.html +649 -0
  41. data/test/fixtures/mobile_route_data/20100323/route_3_index_1.html +721 -0
  42. data/test/fixtures/mobile_route_schedule/20090323/route_18_direction_2_location_25.html +1038 -0
  43. data/test/fixtures/mobile_route_schedule/20090323/route_1_direction_1_location_0.html +1127 -0
  44. data/test/fixtures/mobile_route_schedule/20090323/route_2_direction_2_location_11.html +1430 -0
  45. data/test/fixtures/mobile_route_schedule/20090323/route_2_direction__location_11.html +104 -0
  46. data/test/fixtures/mobile_route_schedule/20100323/route_1_direction_1_location_0.html +1180 -0
  47. data/test/fixtures/mobile_route_schedule/20100323/route_2_direction_2_location_11.html +1554 -0
  48. data/test/fixtures/mobile_route_schedule/20100323/route_3_direction_1_location_0.html +1082 -0
  49. data/test/fixtures/mobile_route_schedule/20100323/route_3_direction_1_location_1.html +1082 -0
  50. data/test/fixtures/mobile_stop_schedule/20090323/location_1987.yml +198 -0
  51. data/test/fixtures/mobile_stop_schedule/20090323/location_1987_route_index_0.html +1283 -0
  52. data/test/fixtures/mobile_stop_schedule/20090323/location_1987_route_index_1.html +194 -0
  53. data/test/fixtures/mobile_stop_schedule/20090323/location_1987_route_index_2.html +116 -0
  54. data/test/fixtures/mobile_stop_schedule/20090323/location_3058_route_index_12.html +149 -0
  55. data/test/fixtures/mobile_stop_schedule/20090323/location_8789_route_index_0.html +1002 -0
  56. data/test/fixtures/mobile_stop_schedule/20100323/location_1987.yml +209 -0
  57. data/test/fixtures/mobile_stop_schedule/20100323/location_1987_route_index_0.html +1393 -0
  58. data/test/fixtures/mobile_stop_schedule/20100323/location_1987_route_index_1.html +206 -0
  59. data/test/fixtures/mobile_stop_schedule/20100323/location_1987_route_index_2.html +123 -0
  60. data/test/fixtures/mobile_stop_schedule/20100323/location_3058_route_index_12.html +278 -0
  61. data/test/fixtures/mobile_stop_schedule/20100323/location_7558_route_index_0.html +979 -0
  62. data/test/fixtures/mobile_stop_schedule/20100323/location_8789_route_index_0.html +1059 -0
  63. data/test/fixtures/stop_resource/1987.html +126 -0
  64. data/test/test_helper.rb +15 -0
  65. data/test/unit/headsign_test.rb +34 -0
  66. data/test/unit/lingo_test.rb +139 -0
  67. data/test/unit/mobile_resource_methods_test.rb +25 -0
  68. data/test/unit/mobile_route_data_test.rb +124 -0
  69. data/test/unit/mobile_route_schedule_test.rb +210 -0
  70. data/test/unit/mobile_stop_schedule_test.rb +153 -0
  71. data/test/unit/service_date_test.rb +27 -0
  72. data/test/unit/stop_resource_test.rb +26 -0
  73. metadata +251 -0
@@ -0,0 +1,98 @@
1
+ require "hpricot"
2
+ require "iconv"
3
+
4
+ module OCTranspo
5
+ module MobileResourceMethods
6
+ include RemoteResourceMethods
7
+
8
+ def site
9
+ "http://www.octranspo.com/mobileweb"
10
+ end
11
+
12
+ def date_stamp (date)
13
+ date.strftime("%Y%m%d")
14
+ end
15
+
16
+ def default_options
17
+ {:index => 0, :date => Date.current}
18
+ end
19
+
20
+ protected
21
+
22
+ # Return a Hpricot DOM representing source_code.
23
+ def interpret (source_code)
24
+ Hpricot(convert_to_utf_8(source_code), :fixup_tags => true)
25
+ end
26
+
27
+ # Return a copy of source_code converted to UTF-8.
28
+ def convert_to_utf_8 (source_code)
29
+ Iconv.new('UTF-8', 'ISO-8859-1').iconv(source_code).sub('charset=iso-8859-1', 'charset=utf-8')
30
+ end
31
+
32
+ # TODO: Use Lingo instead of local regexps.
33
+ def extract_route_and_direction_from (text)
34
+ if matches = /OTrn (.+)/.match(text)
35
+ {:route => "O-Train", :direction => matches[1].strip.mb_chars.upcase}
36
+ elsif matches = /^SHTL SCOTIA BANK PLACE BANQUE SCOTIA/.match(text)
37
+ {:route => nil, :direction => "SHUTTLE TO SCOTIA BANK PLACE BANQUE SCOTIA"}
38
+ elsif matches = /(\d+) (.+)/.match(text)
39
+ {:route => matches[1], :direction => matches[2].strip.mb_chars.upcase}
40
+ else
41
+ raise "Failed to extract route and direction: #{text}"
42
+ end
43
+ end
44
+
45
+ # TODO: Use Lingo instead of local regexps.
46
+ def extract_location_from (text)
47
+ if matches = /(.+) ([1-9][A-E]) +\((\d\d\d\d)\)/.match(text)
48
+ {:station => matches[1], :platform => matches[2], :number => matches[3], :name => "#{matches[1]} #{matches[2]}"}
49
+ elsif matches = /(.+) \((\d\d\d\d)\)/.match(text)
50
+ {:name => matches[1], :number => matches[2]}
51
+ else
52
+ {:name => text.strip}
53
+ end
54
+ end
55
+
56
+ def extract_time_from (text, schedule)
57
+ match = /(\d+):(\d+) (AM|PM)/.match(text)
58
+ if match
59
+ hour = match[1].to_i
60
+ minute = match[2].to_i
61
+ meridian = match[3]
62
+
63
+ if meridian == "AM"
64
+ if hour < 4
65
+ hour = hour + 24
66
+ end
67
+ else
68
+ unless hour == 12
69
+ hour = hour + 12
70
+ end
71
+ end
72
+
73
+ seconds_after_midnight = hour.hours.seconds + minute.minutes.seconds
74
+ return Time.zone.parse(schedule[:date].to_s) + seconds_after_midnight
75
+ end
76
+ end
77
+
78
+ def extract_departure_from (text, schedule)
79
+ flags = extract_flags_from(text)
80
+ destination_flag = schedule[:destinations].keys.detect { |key| flags.delete(key) }
81
+ departure = {}
82
+ departure[:time] = extract_time_from(text, schedule)
83
+ departure[:destination] = schedule[:destinations][destination_flag]
84
+ if flags.any?
85
+ departure[:notes] = flags.map { |key| schedule[:legend][key] }
86
+ end
87
+ departure
88
+ end
89
+
90
+ def extract_flags_from (text)
91
+ if flag_data = /\[(.+)\]/.match(text)
92
+ flag_data[1].split("")
93
+ else
94
+ []
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,85 @@
1
+ module OCTranspo
2
+ module MobileRouteData
3
+
4
+ include MobileResourceMethods
5
+ extend self
6
+
7
+ # Provides an interface for retreiving basic information about an OC Transpo transit route. Data is
8
+ # sourced from http://octranspo.com/mobileweb/jnot/post.routelist.schedules.oci
9
+ #
10
+ # = Usage
11
+ #
12
+ # OCTranspo::MobileRouteData.find returns an array of direction hashes for a single route. Most routes
13
+ # operate in two directions so you will usually receive an array with two items in it. For example:
14
+ #
15
+ # # Find data for OCTranspo bus route 2 on today’s date
16
+ # route_data = OCTranspo::MobileRouteData.find(2)
17
+ #
18
+ # # Bus route 2 has two directions
19
+ # route_data.size # => 2
20
+ #
21
+ # # 2 BAYSHORE is the first direction
22
+ # route_data[0][:route] # => "2"
23
+ # route_data[0][:direction] # => "BAYSHORE"
24
+ # route_data[0][:direction_index] # => "2"
25
+ # route_data[0][:stops] # => [{:name => "RIDEAU 4A", :number => "3009"}, ...]
26
+ #
27
+ # # 2 DOWNTOWN is the opposite direction
28
+ # route_data[1][:route] # => "2"
29
+ # route_data[1][:direction] # => "DOWNTOWN / CENTRE-VILLE"
30
+ # route_data[1][:direction_index] # => "1"
31
+ # route_data[1][:stops] # => [{:name => "BAYSHORE 4B", :number => "3050"}, ...]
32
+ #
33
+ # = Notes
34
+ #
35
+ # The direction_index attributes returned by OCTranspo::MobileRouteData methods are always the values
36
+ # "1" or "2". These values correspond to the direction_index argument in OCTranspo::MobileRouteSchedule.
37
+ # Sometimes the first direction has the value "1", sometimes it has the value "2". When a route only has
38
+ # one direction it usually has the value "1". All in all very confusing.
39
+
40
+ # Returns an array of direction hashes or nil if the route was not found.
41
+ def find (route_name_or_number, options={})
42
+ options[:route] = route_name_or_number
43
+ directions = find_all_directions(options)
44
+ if directions.any?
45
+ return directions
46
+ end
47
+ end
48
+
49
+ def find_all_directions (options={})
50
+ directions = []
51
+ 0.upto(1) do |index|
52
+ directions << find_one_direction(options.merge(:index => index))
53
+ end
54
+ directions.compact
55
+ end
56
+
57
+ def find_one_direction (options={})
58
+ decode(read(options))
59
+ end
60
+
61
+ def url_for (options={})
62
+ options = default_options.merge(options)
63
+ url = "#{site}/jnot/post.routelist.schedules.oci?"
64
+ url << "rangeIndex=5&day=#{date_stamp(options[:date])}"
65
+ url << "&route=#{options[:route]}&routeIndex=#{options[:index]}"
66
+ end
67
+
68
+ def path_for (options={})
69
+ options = default_options.merge(options)
70
+ "#{date_stamp(options[:date])}/route_#{options[:route]}_index_#{options[:index]}.html"
71
+ end
72
+
73
+ def decode (source_code)
74
+ document = interpret(source_code)
75
+ if table_of_stops = document.at("#SchedulesStopListStopsTable")
76
+ direction = extract_route_and_direction_from(table_of_stops.search(:td)[1].inner_text)
77
+ direction[:direction_index] = document.at("#direction")[:value].sub('Direction', '')
78
+ direction[:stops] = table_of_stops.search("td.checkbox").map do |cell|
79
+ extract_location_from(cell.inner_text.strip)
80
+ end
81
+ return direction
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,118 @@
1
+ module OCTranspo
2
+ module MobileRouteSchedule
3
+
4
+ include MobileResourceMethods
5
+ extend self
6
+
7
+ # Provides an interface for retreiving OC Transpo timetables for a specific route, direction and location_index.
8
+ # This API is somewhat less convenient than OCTranpo::MobileStopSchedule.
9
+ #
10
+ # The data returned by this module is sourced from:
11
+ # http://www.octranspo.com/mobileweb/jnot/post.stoplist.schedules.oci
12
+ #
13
+ # == Usage
14
+ #
15
+ # # Find the schedule for the 85 going to HURDMAN from Bayshore Station (the first stop on the route)
16
+ # schedule = OCTranspo::MobileRouteSchedule.find(:route => 85, :direction => "HURDMAN", :location_index => 0)
17
+ # schedule[:route] # => "85"
18
+ # schedule[:direction] # => "HURDMAN"
19
+ # schedule[:location][:name] # => "BAYSHORE 4B"
20
+ # schedule[:location][:number] # => "3050"
21
+ # schedule[:date] # => Date.current
22
+ # schedule[:departures] # => [{:time => Time.zone.parse('04:12'), :destination => "HURDMAN"}, ...]
23
+ #
24
+ # # Find the schedule for the 85 going to HURDMAN from Bronson Ave. & Somerset St. (53rd stop on the route)
25
+ # schedule = OCTranspo::MobileRouteSchedule.find(:route => 85, :direction => "HURDMAN", :location_index => 53)
26
+ # schedule[:route] # => "85"
27
+ # schedule[:direction] # => "HURDMAN"
28
+ # schedule[:location][:name] # => "BRONSON / SOMERSET W-O"
29
+ # schedule[:location][:number] # => "6625"
30
+ # schedule[:date] # => Date.current
31
+ # schedule[:departures] # => [{:time => Time.zone.parse('04:42'), :destination => "HURDMAN"}, ...]
32
+
33
+ # Return a Hpricot DOM representing source_code.
34
+ def interpret (source_code)
35
+ Hpricot(convert_to_utf_8(source_code))
36
+ end
37
+
38
+ def find (options={})
39
+ options[:date] = if options[:date]
40
+ options[:date].to_date
41
+ else
42
+ Date.current
43
+ end
44
+ decode(read(options), options[:date])
45
+ end
46
+
47
+ def find_one (options={})
48
+ options[:date] = if options[:date]
49
+ options[:date].to_date
50
+ else
51
+ Date.current
52
+ end
53
+ decode(read(options), options[:date])
54
+ end
55
+
56
+ def decode (source_code, date)
57
+ document = interpret(source_code)
58
+
59
+ route_and_direction_text = document.at("#SchedulesTimesSelectedTable").search(:tr)[2].search(:td)[1].inner_text
60
+ location_text = document.at("#SchedulesTimesListTable td.header").inner_text
61
+ departure_texts = Array(document.search('#SchedulesTimesListTable td'))[1..-1].map do |cell| cell.inner_text.strip end
62
+
63
+ schedule = {:date => date, :legend => {}}
64
+ schedule.merge! extract_route_and_direction_from(route_and_direction_text)
65
+ schedule[:destinations] = Hash.new(schedule[:direction])
66
+
67
+ Array(document.search("#SchedulesTimesNotesTable td.notes")).in_groups_of(2) do |flag_cell, value_cell|
68
+ flag = flag_cell.inner_text.sub('[', '').sub(']', '').strip
69
+ text = value_cell.inner_text.strip
70
+ if text.include?("Destination")
71
+ schedule[:destinations][flag] = text.sub("Destination ", "")
72
+ else
73
+ schedule[:legend][flag] = text
74
+ end
75
+ end
76
+
77
+ schedule[:location] = extract_location_from(location_text)
78
+ schedule[:departures] = departure_texts.inject([]) do |departures, text|
79
+ departures << extract_departure_from(text, schedule)
80
+ end
81
+
82
+ schedule[:headsigns] = schedule[:departures].map do |d| d[:destination] end.uniq
83
+
84
+ return schedule
85
+ end
86
+
87
+ def default_options
88
+ {:direction_index => 1, :location_index => 0, :date => Date.current}
89
+ end
90
+
91
+ def url_for (options={})
92
+ options = default_options.merge(convert_options(options))
93
+ url = "#{site}/jnot/post.stoplist.schedules.oci?"
94
+ url << "rangeIndex=5&day=#{date_stamp(options[:date])}"
95
+ url << "&route=#{options[:route]}"
96
+ url << "&direction=Direction#{options[:direction_index]}"
97
+ url << "&check#{options[:location_index]}=on"
98
+ end
99
+
100
+ def path_for (options={})
101
+ options = default_options.merge(convert_options(options))
102
+ "#{date_stamp(options[:date])}/route_#{options[:route]}_direction_#{options[:direction_index]}_location_#{options[:location_index]}.html"
103
+ end
104
+
105
+ def convert_options (options={})
106
+ if options[:direction]
107
+ route_data = MobileRouteData.find(options[:route], :date => options[:date])
108
+ direction_data = route_data.detect do |dataset|
109
+ dataset[:direction] === options[:direction]
110
+ end
111
+ if direction_data
112
+ options[:direction_index] = direction_data[:direction_index]
113
+ end
114
+ end
115
+ return options
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,137 @@
1
+ module OCTranspo
2
+ module MobileStopSchedule
3
+
4
+ include MobileResourceMethods
5
+ extend self
6
+
7
+ # Provides an interface for retreiving OCTranspo timetables for a specific route and location. This API
8
+ # is more convenient than OCTranpo::MobileStopSchedule but it doesn’t work for stops without numbers.
9
+ #
10
+ # The data returned by this module is sourced from:
11
+ # http:/octranspo.com/mobileweb/jnot/post.routelist.stoptimes.oci
12
+ #
13
+ # == Usage
14
+ #
15
+ # # Find the schedule for the 85 going to HURDMAN at Bayshore Station (the first stop on the route)
16
+ # schedule = OCTranspo::MobileStopSchedule.find(:route => 85, :direction => "HURDMAN", :location => "3050")
17
+ # schedule[:route] # => "85"
18
+ # schedule[:direction] # => "HURDMAN"
19
+ # schedule[:location][:name] # => "BAYSHORE 4B"
20
+ # schedule[:location][:number] # => "3050"
21
+ # schedule[:date] # => Date.current
22
+ # schedule[:departures] # => [{:time => Time.zone.parse('04:12'), :destination => "HURDMAN"}, ...]
23
+ #
24
+ # # Find the schedule for the 85 going to HURDMAN at Bronson Ave. & Somerset St.
25
+ # schedule = OCTranspo::MobileStopSchedule.find(:route => 85, :direction => "HURDMAN", :location => "6625")
26
+ # schedule[:route] # => "85"
27
+ # schedule[:direction] # => "HURDMAN"
28
+ # schedule[:location][:name] # => "BRONSON / SOMERSET W-O"
29
+ # schedule[:location][:number] # => "6625"
30
+ # schedule[:date] # => Date.current
31
+ # schedule[:departures] # => [{:time => Time.zone.parse('04:42'), :destination => "HURDMAN"}, ...]
32
+
33
+ def find (options={})
34
+ route = "#{options.delete(:route)}"
35
+ direction = "#{options.delete(:direction)}"
36
+ find_all(options).detect do |schedule|
37
+ (schedule[:route] == route) && (schedule[:direction] == direction)
38
+ end
39
+ end
40
+
41
+ def find_all (options={})
42
+ options[:date] ||= default_options[:date]
43
+ if File.exist? index_path_for(options)
44
+ localize YAML.load(open(index_path_for(options)))
45
+ else
46
+ all_routes = []
47
+ while schedule = find_one(options.merge(:route_index => all_routes.size))
48
+ all_routes << schedule
49
+ end
50
+ open index_path_for(options), 'w' do |f|
51
+ YAML.dump all_routes, f
52
+ end
53
+
54
+ find_all(options)
55
+ end
56
+ end
57
+
58
+ def find_one (options={})
59
+ source_code = read(options)
60
+ decode(source_code)
61
+ end
62
+
63
+ def localize (schedules)
64
+ schedules.each do |schedule|
65
+ schedule[:departures].each do |departure|
66
+ departure[:time] = departure[:time].in_time_zone
67
+ end
68
+ end
69
+ end
70
+
71
+ def decode (source_code)
72
+ document = interpret(source_code)
73
+ unless document.at('.InfoBeanError')
74
+ schedule = {:legend => {}}
75
+
76
+ header_rows = document.search("#StopTimesTimesSelectedTable > tr")
77
+
78
+ date_text = header_rows[0].search(:td)[1].inner_text
79
+ schedule.merge! :date => Date.parse(date_text)
80
+
81
+ location_text = header_rows[2].search(:td)[1].inner_text
82
+ schedule.merge! :location => extract_location_from(location_text)
83
+
84
+ route_and_direction_text = header_rows[6].search(:td)[1].inner_text
85
+ schedule.merge! extract_route_and_direction_from(route_and_direction_text)
86
+
87
+ schedule[:destinations] = Hash.new(schedule[:direction])
88
+ header_rows.slice(8, header_rows.size).each do |row|
89
+ cells = row.search(:td)
90
+ flag = /\[(.)\]/.match(cells[0].inner_text)[1]
91
+ text = cells[1].inner_text
92
+ if text.include?("Destination")
93
+ schedule[:destinations][flag] = text.sub("Destination ", "")
94
+ else
95
+ schedule[:legend][flag] = text
96
+ end
97
+ end
98
+
99
+ departure_texts = document.search("#StopTimesTimesListTable0 td").map {|cell| cell.inner_text.strip }
100
+ schedule[:departures] = departure_texts.inject([]) do |departures, text|
101
+ departures << extract_departure_from(text, schedule)
102
+ end
103
+
104
+ schedule[:headsigns] = schedule[:departures].map { |d| d[:destination] }.uniq
105
+
106
+ return schedule
107
+ end
108
+ end
109
+
110
+ def default_options
111
+ {:route_index => 0, :date => Date.current}
112
+ end
113
+
114
+ def url_for (options={})
115
+ options = default_options.merge(options)
116
+ url = "#{site}/jnot/post.routelist.stoptimes.oci?"
117
+ url << "rangeIndex=5&day=#{date_stamp(options[:date])}"
118
+ url << "&stop=#{options[:location]}"
119
+ url << "&check#{options[:route_index]}=on"
120
+ end
121
+
122
+ def path_for (options={})
123
+ options = default_options.merge(options)
124
+ "#{date_stamp(options[:date])}/location_#{options[:location]}_route_index_#{options[:route_index]}.html"
125
+ end
126
+
127
+ def index_path_for (options={})
128
+ options = default_options.merge(options)
129
+ case @source
130
+ when :fixtures
131
+ "#{fixtures_path}/#{date_stamp(options[:date])}/location_#{options[:location]}.yml"
132
+ else
133
+ "#{cache_path}/#{date_stamp(options[:date])}/location_#{options[:location]}.yml"
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,89 @@
1
+ require "open-uri"
2
+
3
+ module OCTranspo
4
+ module RemoteResourceMethods
5
+
6
+ def read (options={})
7
+ # puts url_for(options)
8
+ case @source
9
+ when :fixtures
10
+ read_from_fixture(options)
11
+ else
12
+ read_from_cache(options) || cache(options)
13
+ end
14
+ end
15
+
16
+ def read_from_remote (options)
17
+ url = url_for(options)
18
+ puts "Opening #{url}"
19
+ open(url).read
20
+ end
21
+
22
+ def read_from_fixture (options)
23
+ address = fixture_path_for(options)
24
+ create_fixture(options) unless File.exist?(address)
25
+ open(address).read
26
+ end
27
+
28
+ def read_from_cache (options)
29
+ address = cache_path_for(options)
30
+ if File.exist?(address)
31
+ open(address).read
32
+ end
33
+ end
34
+
35
+ def reset!
36
+ @source = nil
37
+ end
38
+
39
+ def use_fixtures!
40
+ @source = :fixtures
41
+ end
42
+
43
+ def site; end
44
+
45
+ def url_for (options={}); end
46
+
47
+ def path_for (options={}); end
48
+
49
+ def fixture_path_for (options={});
50
+ "#{fixtures_path}/#{path_for(options)}"
51
+ end
52
+
53
+ def cache_path_for (options={});
54
+ "#{cache_path}/#{path_for(options)}"
55
+ end
56
+
57
+ def fixtures_path
58
+ "test/fixtures/#{self.name.demodulize.underscore}"
59
+ end
60
+
61
+ def cache_path
62
+ "cache/octranspo/#{self.name.demodulize.underscore}"
63
+ end
64
+
65
+ def create_fixture (options={})
66
+ address = fixture_path_for(options)
67
+ puts "Creating fixture #{address}"
68
+ system "mkdir -p #{File.dirname(address)}"
69
+ File.open(address, "w") do |f|
70
+ f.write read_from_remote(options)
71
+ end
72
+ read_from_fixture(options)
73
+ end
74
+
75
+ def cache (options={})
76
+ address = cache_path_for(options)
77
+ system "mkdir -p #{File.dirname(address)}"
78
+ File.open(address, "w") do |f|
79
+ f.write read_from_remote(options)
80
+ end
81
+ puts "Cached #{address}"
82
+ read_from_cache(options)
83
+ end
84
+
85
+ def logger
86
+ RAILS_DEFAULT_LOGGER
87
+ end
88
+ end
89
+ end