national-rail 0.3.8 → 0.3.10

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 (2) hide show
  1. data/lib/national-rail/journey_planner.rb +54 -14
  2. metadata +85 -6
@@ -5,8 +5,34 @@ require 'tidy_ffi'
5
5
 
6
6
  module NationalRail
7
7
 
8
+ class ParseError < StandardError
9
+ attr_reader :original_exception, :page_html
10
+ def initialize(original_exception, page_html)
11
+ super(original_exception.message)
12
+ @original_exception, @page_html = original_exception, page_html
13
+ end
14
+ def inspect
15
+ "#{self.class} wrapping #{@original_exception.inspect}"
16
+ end
17
+ end
18
+
19
+ class InputError < StandardError; end
20
+
8
21
  class JourneyPlanner
9
22
 
23
+ class << self
24
+ attr_accessor :capture_path
25
+ def capture(page, filename)
26
+ if capture_path.present?
27
+ FileUtils.mkdir_p(capture_path)
28
+ path = File.join(capture_path, filename)
29
+ File.open(path, "w") { |f| f.write(TidyFFI::Tidy.new(page.parser.to_html).clean) }
30
+ end
31
+ rescue => e
32
+ puts e
33
+ end
34
+ end
35
+
10
36
  class NokogiriParser < Mechanize::Page
11
37
  attr_reader :doc
12
38
  def initialize(uri = nil, response = nil, body = nil, code = nil)
@@ -38,23 +64,32 @@ module NationalRail
38
64
 
39
65
  attr_reader :departure_time, :number_of_changes
40
66
 
41
- def initialize(agent, date, departure_time, number_of_changes, link)
67
+ def initialize(agent, date, departure_time, number_of_changes, link, status)
42
68
  @agent, @date = agent, date
43
69
  @departure_time, @number_of_changes, @link = departure_time, number_of_changes, link
70
+ @status = status
71
+ end
72
+
73
+ def cancelled?
74
+ @status =~ %r{cancelled}i
44
75
  end
45
76
 
46
77
  def details
47
- return if number_of_changes.to_i > 0
78
+ return {} if number_of_changes.to_i > 0
79
+ return {} if cancelled?
48
80
  @agent.transact do
49
- parse_details(@link.click, @date)
81
+ details_page = @link.click
82
+ JourneyPlanner.capture(details_page, "details.html")
83
+ parse_details(details_page, @date)
50
84
  end
51
85
  end
52
86
 
53
87
  def parse_details(page, date)
54
88
  details = {}
55
89
  description = (page.doc/"table#journeyLegDetails tbody tr.lastRow td[@colspan='6'] div").last.inner_text.gsub(/\s+/, " ").strip
56
- company = (/(.*) service from .* to .*/.match(description)[1]).strip
57
- details[:company] = company
90
+ company_matches = /(.*) service from .* to .*/.match(description)
91
+ return details unless company_matches
92
+ details[:company] = company_matches[1].strip
58
93
  origins, destinations = (/.* service from (.*) to (.*)/.match(description)[1,2]).map{ |s| s.split(",").map(&:strip) }
59
94
  details[:origins], details[:destinations] = origins, destinations
60
95
  parser = TimeParser.new(date)
@@ -90,9 +125,9 @@ module NationalRail
90
125
  }
91
126
  details
92
127
  rescue => e
93
- filename = File.join(File.dirname(__FILE__), "..", "..", "details-error.html")
94
- File.open(filename, "w") { |f| f.write(page.parser.to_html) }
95
- raise e
128
+ JourneyPlanner.capture(page, "details-error.html")
129
+ page_html = TidyFFI::Tidy.new(page.parser.to_html).clean
130
+ raise ParseError.new(e, page_html)
96
131
  end
97
132
  end
98
133
 
@@ -106,6 +141,7 @@ module NationalRail
106
141
  def plan(options = {})
107
142
  summary_rows = []
108
143
  @agent.get("http://www.nationalrail.co.uk/") do |home_page|
144
+ JourneyPlanner.capture(home_page, "index.html")
109
145
  button = nil
110
146
  times_page = home_page.form_with(:action => "http://ojp.nationalrail.co.uk/en/s/planjourney/plan") do |form|
111
147
  button = form.buttons.last
@@ -132,8 +168,10 @@ module NationalRail
132
168
  form["_includeOvertakenTrains"] = "on"
133
169
  end.click_button(button)
134
170
 
171
+ JourneyPlanner.capture(times_page, "summary.html")
172
+
135
173
  if (times_page.doc/".error-message").any?
136
- raise (times_page.doc/".error-message").first.inner_text.gsub(/\s+/, " ").strip
174
+ raise InputError.new((times_page.doc/".error-message").first.inner_text.gsub(/\s+/, " ").strip)
137
175
  end
138
176
 
139
177
  date = Date.parse((times_page.doc/".journey-details span").first.children.first.inner_text.gsub(/\s+/, " ").gsub(/\+ 1 day/, '').strip)
@@ -145,22 +183,24 @@ module NationalRail
145
183
  next
146
184
  end
147
185
 
148
- departure_time = TimeParser.new(date).time((tr/"td.leaving").inner_text.strip)
186
+ departure_time = TimeParser.new(date).time((tr/"td:nth-child(1)").inner_text.strip)
149
187
  number_of_changes = (tr/"td:nth-child(6)").inner_text.strip
188
+ status = (tr/"td:nth-child(10) .status").inner_text.strip
150
189
 
151
190
  anchor = (tr/"a[@id^=journeyOption]").first
152
191
  next unless anchor
153
192
 
154
193
  link = times_page.links.detect { |l| l.attributes["id"] == anchor.attributes["id"].value }
155
194
 
156
- summary_rows << SummaryRow.new(@agent, date, departure_time, number_of_changes, link)
195
+ summary_rows << SummaryRow.new(@agent, date, departure_time, number_of_changes, link, status)
157
196
  end
158
197
  end
159
198
  summary_rows
160
199
  rescue => e
161
- filename = File.join(File.dirname(__FILE__), "..", "..", "summary-error.html")
162
- File.open(filename, "w") { |f| f.write(TidyFFI::Tidy.new(@agent.current_page.parser.to_html).clean) }
163
- raise e
200
+ page = @agent.current_page
201
+ JourneyPlanner.capture(page, "summary-error.html")
202
+ page_html = TidyFFI::Tidy.new(page.parser.to_html).clean
203
+ raise ParseError.new(e, page_html)
164
204
  end
165
205
  end
166
206
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: national-rail
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 7
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 3
8
- - 8
9
- version: 0.3.8
9
+ - 10
10
+ version: 0.3.10
10
11
  platform: ruby
11
12
  authors:
12
13
  - James Mead
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-11-17 00:00:00 +00:00
18
+ date: 2010-12-05 00:00:00 +00:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: mechanize
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ~>
26
28
  - !ruby/object:Gem::Version
29
+ hash: 23
27
30
  segments:
28
31
  - 1
29
32
  - 0
@@ -35,9 +38,11 @@ dependencies:
35
38
  name: hpricot
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ~>
40
44
  - !ruby/object:Gem::Version
45
+ hash: 59
41
46
  segments:
42
47
  - 0
43
48
  - 8
@@ -49,9 +54,11 @@ dependencies:
49
54
  name: nokogiri
50
55
  prerelease: false
51
56
  requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
52
58
  requirements:
53
59
  - - ~>
54
60
  - !ruby/object:Gem::Version
61
+ hash: 15
55
62
  segments:
56
63
  - 1
57
64
  - 4
@@ -63,9 +70,11 @@ dependencies:
63
70
  name: activesupport
64
71
  prerelease: false
65
72
  requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
66
74
  requirements:
67
75
  - - ~>
68
76
  - !ruby/object:Gem::Version
77
+ hash: 7
69
78
  segments:
70
79
  - 3
71
80
  - 0
@@ -74,19 +83,85 @@ dependencies:
74
83
  type: :runtime
75
84
  version_requirements: *id004
76
85
  - !ruby/object:Gem::Dependency
77
- name: tidy_ffi
86
+ name: ffi
78
87
  prerelease: false
79
88
  requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - "="
92
+ - !ruby/object:Gem::Version
93
+ hash: 1
94
+ segments:
95
+ - 0
96
+ - 6
97
+ - 3
98
+ version: 0.6.3
99
+ type: :runtime
100
+ version_requirements: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ name: tidy_ffi
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
80
106
  requirements:
81
107
  - - ~>
82
108
  - !ruby/object:Gem::Version
109
+ hash: 29
83
110
  segments:
84
111
  - 0
85
112
  - 1
86
113
  - 3
87
114
  version: 0.1.3
88
115
  type: :runtime
89
- version_requirements: *id005
116
+ version_requirements: *id006
117
+ - !ruby/object:Gem::Dependency
118
+ name: i18n
119
+ prerelease: false
120
+ requirement: &id007 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ hash: 13
126
+ segments:
127
+ - 0
128
+ - 4
129
+ - 1
130
+ version: 0.4.1
131
+ type: :runtime
132
+ version_requirements: *id007
133
+ - !ruby/object:Gem::Dependency
134
+ name: tzinfo
135
+ prerelease: false
136
+ requirement: &id008 !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ hash: 61
142
+ segments:
143
+ - 0
144
+ - 3
145
+ - 23
146
+ version: 0.3.23
147
+ type: :runtime
148
+ version_requirements: *id008
149
+ - !ruby/object:Gem::Dependency
150
+ name: webmock
151
+ prerelease: false
152
+ requirement: &id009 !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ hash: 13
158
+ segments:
159
+ - 1
160
+ - 6
161
+ - 1
162
+ version: 1.6.1
163
+ type: :development
164
+ version_requirements: *id009
90
165
  description:
91
166
  email: james@floehopper.org
92
167
  executables: []
@@ -113,23 +188,27 @@ rdoc_options: []
113
188
  require_paths:
114
189
  - lib
115
190
  required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
116
192
  requirements:
117
193
  - - ">="
118
194
  - !ruby/object:Gem::Version
195
+ hash: 3
119
196
  segments:
120
197
  - 0
121
198
  version: "0"
122
199
  required_rubygems_version: !ruby/object:Gem::Requirement
200
+ none: false
123
201
  requirements:
124
202
  - - ">="
125
203
  - !ruby/object:Gem::Version
204
+ hash: 3
126
205
  segments:
127
206
  - 0
128
207
  version: "0"
129
208
  requirements: []
130
209
 
131
210
  rubyforge_project: national-rail
132
- rubygems_version: 1.3.6
211
+ rubygems_version: 1.3.7
133
212
  signing_key:
134
213
  specification_version: 3
135
214
  summary: A Ruby API for the National Rail website