picturehouse_uk 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/CHANGELOG.md +18 -0
  4. data/README.md +7 -10
  5. data/Rakefile +20 -7
  6. data/lib/picturehouse_uk.rb +4 -1
  7. data/lib/picturehouse_uk/cinema.rb +51 -100
  8. data/lib/picturehouse_uk/film.rb +22 -8
  9. data/lib/picturehouse_uk/internal/address_parser.rb +72 -0
  10. data/lib/picturehouse_uk/internal/cinema_page.rb +35 -0
  11. data/lib/picturehouse_uk/internal/film_with_screenings_parser.rb +87 -37
  12. data/lib/picturehouse_uk/internal/title_sanitizer.rb +49 -0
  13. data/lib/picturehouse_uk/internal/website.rb +39 -0
  14. data/lib/picturehouse_uk/screening.rb +63 -19
  15. data/lib/picturehouse_uk/version.rb +2 -2
  16. data/picturehouse_uk.gemspec +11 -11
  17. data/test/fixture_updater.rb +43 -0
  18. data/test/fixtures/address-fragments/duke-of-yorks.html +39 -0
  19. data/test/fixtures/address-fragments/hackney-picturehouse.html +12 -0
  20. data/test/fixtures/cinema/Duke_Of_Yorks.html +4370 -0
  21. data/test/fixtures/cinema/Duke_Of_Yorks/film_last.html +45 -0
  22. data/test/fixtures/cinema/Duke_Of_Yorks/film_second.html +37 -0
  23. data/test/fixtures/{abbeygate-contact-us.html → contact_us/Duke_Of_Yorks.html} +635 -156
  24. data/test/fixtures/{dukes-at-komedia-contact-us.html → contact_us/Dukes_At_Komedia.html} +582 -98
  25. data/test/fixtures/{picturehouses-homepage.html → home.html} +642 -146
  26. data/test/lib/picturehouse_uk/cinema_test.rb +127 -307
  27. data/test/lib/picturehouse_uk/film_test.rb +65 -16
  28. data/test/lib/picturehouse_uk/internal/address_parser_test.rb +55 -0
  29. data/test/lib/picturehouse_uk/internal/cinema_page_test.rb +51 -0
  30. data/test/lib/picturehouse_uk/internal/film_with_screenings_parser_test.rb +44 -151
  31. data/test/lib/picturehouse_uk/internal/title_sanitizer_test.rb +131 -0
  32. data/test/lib/picturehouse_uk/internal/website_test.rb +64 -0
  33. data/test/lib/picturehouse_uk/screening_test.rb +149 -21
  34. data/test/live/integration_test.rb +68 -0
  35. data/test/test_helper.rb +3 -1
  36. metadata +40 -43
  37. data/test/fixtures/dukes-at-komedia-cinema.html +0 -7148
  38. data/test/fixtures/film_node/blue-jasmine-done.html +0 -53
  39. data/test/fixtures/film_node/blue-jasmine-future.html +0 -55
  40. data/test/fixtures/film_node/bolshoi-spartacus.html +0 -26
  41. data/test/fixtures/film_node/captain-phillips-with-silver-screen-and-subtitles.html +0 -103
  42. data/test/fixtures/film_node/fifth-estate-with-big-scream.html +0 -73
  43. data/test/fixtures/film_node/london-film-festival-with-toddler-time.html +0 -46
  44. data/test/fixtures/film_node/met-encore-rusalka-as-live.html +0 -26
  45. data/test/fixtures/film_node/nt-encore-hamlet.html +0 -26
  46. data/test/fixtures/film_node/planes-with-kids-club.html +0 -77
  47. data/test/fixtures/film_node/royal-opera-house-don-quixote.html +0 -26
  48. data/test/fixtures/film_node/rsc-encore-richard-ii.html +0 -28
  49. data/test/fixtures/film_node/rsc-live-richard-ii.html +0 -41
  50. data/test/fixtures/film_node/rsc-live-the-two-gentlemen-of-verona-zero-cert.html +0 -19
  51. data/test/fixtures/hackney-contact-us.html +0 -998
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 944f2d9ed771bfd8d95ceea29fda42f77346ef03
4
- data.tar.gz: 87cd57db1cbe6ffc6ceb949332749ed94180620a
3
+ metadata.gz: 852cffd41d42e302152ccedd703e8f265b48015f
4
+ data.tar.gz: a2cfd6c6dbb93d841cc2d7c22423d9228363d342
5
5
  SHA512:
6
- metadata.gz: 398e86805f4619f29d567599c775b7f5e101806809ccac053b6b3098ccadccf2a8f2872019e64d6bed8cfbca4a722cfd97b7038e05ec97e87205eb08ca65d954
7
- data.tar.gz: b37051a1d76065d43c293c115abd37d0e1f77b32e932c139b8600ee23c698ac26235ce92b2b25ca276ea71db44fa3021197817c5de812a897ab631dcc0e0964c
6
+ metadata.gz: a5da4c31df5e98af0f65e4261eca2de02da13e6f5f80ab5a75171c7b393537e801bab7740cffdfee6ce39caa6994165c3ddc4c91e28ba3f26367590c31863de3
7
+ data.tar.gz: 36e769a6373c03914f241ca65babc5e878552902627d53b6123bdc99918a605009ba0dcc41815933139c918925d7d84be828496f2dfb0853c051e9efcde3f429
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0.0
4
+ - 2.1.3
5
+ script: "rake && rake live"
@@ -0,0 +1,18 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ ## 2.0.0 - 2014-10-16
5
+
6
+ ### Added
7
+ - Live testing rake task
8
+ - Ruby 2.1.3 on Travis
9
+
10
+ ### Changed
11
+ - Internal structure of parsers
12
+ - Title sanitization
13
+ - Broke up monolith of Cinema class
14
+ - Fixture update
15
+ - Rubocop
16
+
17
+ ### Removed
18
+ - Only the badness
data/README.md CHANGED
@@ -5,6 +5,7 @@ A simple gem to parse the [Picturehouse Cinemas UK website](http://picturehouses
5
5
  [![Gem Version](https://badge.fury.io/rb/picturehouse_uk.png)](http://badge.fury.io/rb/picturehouse_uk)
6
6
  [![Code Climate](https://codeclimate.com/github/andycroll/picturehouse_uk.png)](https://codeclimate.com/github/andycroll/picturehouse_uk)
7
7
  [![Build Status](https://travis-ci.org/andycroll/picturehouse_uk.png?branch=master)](https://travis-ci.org/andycroll/picturehouse_uk)
8
+ [![Inline docs](http://inch-ci.org/github/andycroll/picturehouse_uk.png)](http://inch-ci.org/github/andycroll/picturehouse_uk)
8
9
 
9
10
  ## Installation
10
11
 
@@ -26,12 +27,13 @@ Or install it yourself as:
26
27
 
27
28
  ``` ruby
28
29
  PicturehouseUK::Cinema.all
29
- #=> [<PicturehouseUK::Cinema brand="Picturehouse" name="Duke's At Komedia" slug="dukes-at-komedia" chain_id="Dukes_At_Komedia" url="...">, #=> <PicturehouseUK::Cinema brand="Picturehouse" name="Duke o York's" slug="duke-of-yorks" chain_id="Duke_Of_Yorks" url="...">, ...]
30
+ #=> [
31
+ <PicturehouseUK::Cinema brand="Picturehouse" name="Duke's at Komedia" slug="dukes-at-komedia" chain_id="Dukes_At_Komedia" url="...">,
32
+ <PicturehouseUK::Cinema brand="Picturehouse" name="Duke of York's" slug="duke-of-yorks" chain_id="Duke_Of_Yorks" url="...">,
33
+ ...
34
+ ]
30
35
 
31
- PicturehouseUK::Cinema.find_by_id('Duke_Of_Yorks')
32
- #=> <PicturehouseUK::Cinema brand="Picturehouse" name="Duke_Of_Yorks" slug="duke-of-yorks" address="..." chain_id="Duke_Of_Yorks" url="...">
33
-
34
- cinema = PicturehouseUK::Cinema.find_by_slug('duke-of-yorks')
36
+ PicturehouseUK::Cinema.find('Duke_Of_Yorks')
35
37
  #=> <PicturehouseUK::Cinema brand="Picturehouse" name="Duke_Of_Yorks" slug="duke-of-yorks" address="..." chain_id="Duke_Of_Yorks" url="...">
36
38
 
37
39
  cinema.brand
@@ -49,11 +51,6 @@ cinema.films
49
51
  cinema.screenings
50
52
  #=> [<PicturehouseUK::Screening film="About Time" when="2013-09-09 11:00 UTC" varient="3d">, <PicturehouseUK::Screening film="Iron Man 3" when="2013-09-09 13:50 UTC" varient="kids">, <PicturehouseUK::Screening ..>, <PicturehouseUK::Screening ...>]
51
53
 
52
- cinema.screenings_of 'Iron Man 3'
53
- #=> [<PicturehouseUK::Screening film="Iron Man 3" when="2013-09-09 11:00 UTC" varient="3d">, <PicturehouseUK::Screening film="Iron Man 3" when="2013-09-09 13:50 UTC" varient="kids">]
54
-
55
- cinema.screenings_of <PicturehouseUK::Film name="Iron Man 3">
56
- #=> [<PicturehouseUK::Screening film="Iron Man 3" when="2013-09-09 11:00 UTC" varient="3d">, <PicturehouseUK::Screening film="Iron Man 3" when="2013-09-09 13:50 UTC" varient="kids">]
57
54
  ```
58
55
 
59
56
  ## Contributing
data/Rakefile CHANGED
@@ -1,20 +1,33 @@
1
1
  #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
2
+ require 'bundler/gem_tasks'
3
3
 
4
4
  require 'rake/testtask'
5
5
 
6
6
  Rake::TestTask.new do |t|
7
7
  t.libs << 'lib/picturehouse_uk'
8
- t.test_files = FileList['test/lib/picturehouse_uk/*_test.rb', 'test/lib/picturehouse_uk/internal/*_test.rb']
8
+ t.test_files = FileList[
9
+ 'test/lib/picturehouse_uk/*_test.rb',
10
+ 'test/lib/picturehouse_uk/internal/*_test.rb'
11
+ ]
9
12
  t.verbose = true
10
13
  end
11
14
 
12
- task :build do
13
- system "gem build picturehouse_uk.gemspec"
15
+ Rake::TestTask.new do |t|
16
+ t.libs << 'lib/picturehouse_uk'
17
+ t.name = :live
18
+ t.test_files = FileList[
19
+ 'test/live/*_test.rb'
20
+ ]
21
+ t.verbose = true
14
22
  end
15
23
 
16
- task :release => :build do
17
- system "gem push picturehouse_uk-#{PicturehouseUk::VERSION}"
24
+ # http://erniemiller.org/2014/02/05/7-lines-every-gems-rakefile-should-have/
25
+ task :console do
26
+ require 'irb'
27
+ require 'irb/completion'
28
+ require 'picturehouse_uk'
29
+ ARGV.clear
30
+ IRB.start
18
31
  end
19
32
 
20
- task :default => :test
33
+ task default: :test
@@ -1,11 +1,14 @@
1
- require 'httparty'
2
1
  require 'nokogiri'
3
2
  require 'tzinfo'
4
3
  require 'tzinfo/data'
5
4
 
6
5
  require_relative './picturehouse_uk/version'
7
6
 
7
+ require_relative './picturehouse_uk/internal/address_parser'
8
+ require_relative './picturehouse_uk/internal/cinema_page'
8
9
  require_relative './picturehouse_uk/internal/film_with_screenings_parser'
10
+ require_relative './picturehouse_uk/internal/title_sanitizer'
11
+ require_relative './picturehouse_uk/internal/website'
9
12
 
10
13
  require_relative './picturehouse_uk/cinema'
11
14
  require_relative './picturehouse_uk/film'
@@ -1,7 +1,10 @@
1
1
  module PicturehouseUk
2
-
3
2
  # The object representing a cinema on the Picturehouse UK website
4
3
  class Cinema
4
+ # address css
5
+ ADDRESS_CSS = '.box6 .txt6'
6
+ # cinema link css
7
+ CINEMA_LINKS_CSS = '#cinemalisthome .cinemas a'
5
8
 
6
9
  # @return [String] the brand of the cinema
7
10
  attr_reader :brand
@@ -14,27 +17,27 @@ module PicturehouseUk
14
17
  # @return [String] the url of the cinema on the Picturehouse website
15
18
  attr_reader :url
16
19
 
17
- # @param [String] id cinema id from the site
18
- # @param [String] name cinema name
19
- # @param [String] url url on Picturehouse website
20
+ # @param [Hash] options id, name and url of the cinemas
20
21
  # @return [PicturehouseUk::Cinema]
21
- def initialize(id, name, url)
22
+ def initialize(options)
22
23
  @brand = 'Picturehouse'
23
- @id = id
24
- @name = name
25
- @slug = name.downcase.gsub(/[^0-9a-z ]/,'').gsub(/\s+/, '-')
26
- @url = (url[0] == '/') ? "http://www.picturehouses.co.uk#{url}" : url
24
+ @id = options[:id]
25
+ @name = options[:name]
26
+ @slug = @name.downcase.gsub(/[^0-9a-z ]/, '').gsub(/\s+/, '-')
27
+ @url = if options[:url][0] == '/'
28
+ "http://www.picturehouses.co.uk#{options[:url]}"
29
+ else
30
+ options[:url]
31
+ end
27
32
  end
28
33
 
29
34
  # Return basic cinema information for all cinemas
30
35
  # @return [Array<PicturehouseUk::Cinema>]
31
36
  # @example
32
37
  # PicturehouseUk::Cinema.all
33
- # # => [<PicturehouseUK::Cinema brand="Picturehouse" name="Duke's At Komedia" slug="dukes-at-komedia" id="Dukes_At_Komedia" url="...">, #=> <PicturehouseUK::Cinema brand="Picturehouse" name="Duke o York's" slug="duke-of-yorks" id="Duke_Of_Yorks" url="...">, ...]
38
+ # # => [<PicturehouseUK::Cinema ...>, <PicturehouseUK::Cinema ...>, ...]
34
39
  def self.all
35
- cinema_links.map do |link|
36
- new_from_link link
37
- end
40
+ cinema_links.map { |link| new_from_link(link) }
38
41
  end
39
42
 
40
43
  # Find a single cinema
@@ -42,9 +45,9 @@ module PicturehouseUk
42
45
  # @return [PicturehouseUk::Cinema, nil]
43
46
  # @example
44
47
  # PicturehouseUk::Cinema.find('Dukes_At_Komedia')
45
- # # => <PicturehouseUK::Cinema brand="Picturehouse" name="Duke's At Komedia" slug="dukes-at-komedia" id="Dukes_At_Komedia" url="...">
48
+ # # => <PicturehouseUK::Cinema ...>
46
49
  def self.find(id)
47
- all.select { |cinema| cinema.id == id }[0]
50
+ all.find { |cinema| cinema.id == id }
48
51
  end
49
52
 
50
53
  # Address of the cinema
@@ -52,16 +55,16 @@ module PicturehouseUk
52
55
  # @example
53
56
  # cinema = PicturehouseUk::Cinema.find('Dukes_At_Komedia')
54
57
  # cinema.adr
55
- # #=> { street_address: '44-47 Gardner Street', extended_address: 'North Laine', locality: 'Brighton', postal_code: 'BN1 1UN', country_name: 'United Kingdom' }
56
- # @note Uses the standard method naming as at http://microformats.org/wiki/adr
58
+ # #=> {
59
+ # street_address: '44-47 Gardner Street',
60
+ # extended_address: 'North Laine',
61
+ # locality: 'Brighton',
62
+ # postal_code: 'BN1 1UN',
63
+ # country_name: 'United Kingdom'
64
+ # }
65
+ # @note Uses method naming as at http://microformats.org/wiki/adr
57
66
  def adr
58
- {
59
- street_address: street_address,
60
- extended_address: extended_address,
61
- locality: locality,
62
- postal_code: postal_code,
63
- country: 'United Kingdom'
64
- }
67
+ PicturehouseUk::Internal::AddressParser.new(address_node.to_s).address
65
68
  end
66
69
  alias_method :address, :adr
67
70
 
@@ -71,9 +74,9 @@ module PicturehouseUk
71
74
  # cinema = PicturehouseUk::Cinema.find('Dukes_At_Komedia')
72
75
  # cinema.extended_address
73
76
  # #=> 'North Laine'
74
- # @note Uses the standard method naming as at http://microformats.org/wiki/adr
77
+ # @note Uses method naming as at http://microformats.org/wiki/adr
75
78
  def extended_address
76
- address_strings.length > 3 ? address_strings[1] : nil
79
+ address[:extended_address]
77
80
  end
78
81
 
79
82
  # Films with showings scheduled at this cinema
@@ -81,12 +84,9 @@ module PicturehouseUk
81
84
  # @example
82
85
  # cinema = PicturehouseUk::Cinema.find('Dukes_At_Komedia')
83
86
  # cinema.films
84
- # # => [<PicturehouseUk::Film name="Iron Man 3">, <PicturehouseUk::Film name="Star Trek Into Darkness">]
87
+ # # => [<PicturehouseUk::Film ...>, <PicturehouseUk::Film ...>, ...]
85
88
  def films
86
- film_nodes.map do |node|
87
- parser = PicturehouseUk::Internal::FilmWithScreeningsParser.new node.to_s
88
- PicturehouseUk::Film.new parser.film_name
89
- end.uniq
89
+ PicturehouseUk::Film.at(@id)
90
90
  end
91
91
 
92
92
  # The name of the cinema (might include brand)
@@ -107,7 +107,7 @@ module PicturehouseUk
107
107
  # #=> 'Brighton'
108
108
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
109
109
  def locality
110
- address_strings[-2]
110
+ address[:locality]
111
111
  end
112
112
 
113
113
  # Post code of the cinema
@@ -118,7 +118,7 @@ module PicturehouseUk
118
118
  # #=> 'BN1 1UN'
119
119
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
120
120
  def postal_code
121
- address_strings[-1]
121
+ address[:postal_code]
122
122
  end
123
123
 
124
124
  # All planned screenings
@@ -126,17 +126,9 @@ module PicturehouseUk
126
126
  # @example
127
127
  # cinema = PicturehouseUk::Cinema.find('Dukes_At_Komedia')
128
128
  # cinema.screenings
129
- # # => [<PicturehouseUk::Screening film_name="Iron Man 3" cinema_name="Duke's At Komedia" when="..." variant="...">, <PicturehouseUk::Screening ...>]
129
+ # # => [<PicturehouseUk::Screening ...>, <PicturehouseUk::Screening ...>]
130
130
  def screenings
131
- film_nodes.map do |node|
132
- parser = PicturehouseUk::Internal::FilmWithScreeningsParser.new node.to_s
133
- parser.showings.map do |screening_type, times|
134
- times.map do |time|
135
- variant = screening_type == '2d' ? nil : screening_type
136
- PicturehouseUk::Screening.new parser.film_name, self.name, time, variant
137
- end
138
- end
139
- end.flatten
131
+ PicturehouseUk::Screening.at(@id)
140
132
  end
141
133
 
142
134
  # The street adress of the cinema
@@ -147,79 +139,38 @@ module PicturehouseUk
147
139
  # #=> '44-47 Gardner Street'
148
140
  # @note Uses the standard method naming as at http://microformats.org/wiki/adr
149
141
  def street_address
150
- address_strings[0]
142
+ address[:street_address]
151
143
  end
152
144
 
153
145
  private
154
146
 
155
147
  def self.cinema_links
156
- parsed_homepage.css('#cinemalisthome .cinemas a')
148
+ home_doc.css(CINEMA_LINKS_CSS)
157
149
  end
158
150
 
159
- def self.homepage_response
160
- @homepage_response ||= HTTParty.get('http://www.picturehouses.co.uk/')
161
- end
162
-
163
- def self.new_from_link(link)
164
- url = link.get_attribute('href')
165
- id = url.match(/\/cinema\/(.+)\/$/)[1]
166
- name = link.css('span:nth-child(2)').text
167
- new id, name, url
151
+ def self.home_doc
152
+ @home_doc ||= Nokogiri::HTML(website.home)
168
153
  end
169
154
 
170
- def self.parsed_homepage
171
- Nokogiri::HTML(homepage_response)
155
+ def self.website
156
+ @website ||= PicturehouseUk::Internal::Website.new
172
157
  end
173
158
 
174
- def address_parts
175
- if pure_address_parts.length > 0 && pure_address_parts[0].match(/\d+\Z/)
176
- ["#{pure_address_parts[0]} #{pure_address_parts[1]}"] + pure_address_parts[2..-1]
177
- else
178
- pure_address_parts
179
- end
180
- end
181
-
182
- def address_strings
183
- if address_parts && address_parts.length > 0
184
- address_parts[0..post_code_index]
185
- else
186
- # this is a horrendous hack for Hackney Picturehouse
187
- address_node.css('p').to_s.split('Box Office')[0].split('<br> ')[1..-1]
188
- end
159
+ def self.new_from_link(link)
160
+ url = link.get_attribute('href')
161
+ new(
162
+ id: url.match(%r{/cinema/(.+)/$})[1],
163
+ name: link.css('span:nth-child(2)').text,
164
+ url: url
165
+ )
189
166
  end
190
167
 
191
168
  def address_node
192
- parsed_contact_us.css('.box6 .txt6')
193
- end
194
-
195
- def contact_us_response
196
- @contact_us_response ||= HTTParty.get("#{@url}Hires_Info/Contact_Us/")
197
- end
198
-
199
- def cinema_response
200
- @cinema_response ||= HTTParty.get(@url)
201
- end
202
-
203
- def film_nodes
204
- parsed_cinema.css('.box8_content .largelist .item')
205
- end
206
-
207
- def parsed_cinema
208
- Nokogiri::HTML(cinema_response)
209
- end
210
-
211
- def parsed_contact_us
212
- Nokogiri::HTML(contact_us_response)
213
- end
214
-
215
- def post_code_index
216
- address_parts.index { |e| e.match /[A-Z]{1,2}\d{1,2}[A-Z]?\s\d{1,2}[A-Z]{1,2}/ }
169
+ @address_node ||= contact_us_doc.css(ADDRESS_CSS)
217
170
  end
218
171
 
219
- def pure_address_parts
220
- @pure_address_parts = address_node.css('.cinemaListBox').map do |e|
221
- e.children[0].to_s
222
- end.select { |e| e != '' }
172
+ def contact_us_doc
173
+ @contact_us_doc ||= Nokogiri::HTML(self.class.website.contact_us(id))
223
174
  end
224
175
  end
225
176
  end
@@ -1,5 +1,4 @@
1
1
  module PicturehouseUk
2
-
3
2
  # A film on the Picturehouse UK website
4
3
  class Film
5
4
  include Comparable
@@ -13,14 +12,23 @@ module PicturehouseUk
13
12
  # @return [PicturehouseUk::Film]
14
13
  def initialize(name)
15
14
  @name = name
16
- @slug = name.downcase.gsub(/[^0-9a-z ]/,'').gsub(/\s+/, '-')
15
+ @slug = name.downcase.gsub(/[^0-9a-z ]/, '').gsub(/\s+/, '-')
16
+ end
17
+
18
+ # Films at a single cinema
19
+ # @param [String] cinema_id the id of the cinema
20
+ # @return [Array<PicturehouseUk::Film>]
21
+ def self.at(cinema_id)
22
+ cinema_page(cinema_id).film_html.map do |html|
23
+ new(Internal::FilmWithScreeningsParser.new(html).film_name)
24
+ end.uniq
17
25
  end
18
26
 
19
27
  # Allows sort on objects
20
28
  # @param [PicturehouseUk::Film] other another film object
21
29
  # @return [Integer] -1, 0 or 1
22
- def <=> other
23
- self.slug <=> other.slug
30
+ def <=>(other)
31
+ slug <=> other.slug
24
32
  end
25
33
 
26
34
  # Check an object is the same as another object.
@@ -28,20 +36,26 @@ module PicturehouseUk
28
36
  # @return [Boolean] True if both objects are the same exact object, or if
29
37
  # they are of the same type and share an equal slug
30
38
  # @note Guided by http://woss.name/2011/01/20/equality-comparison-and-ordering-in-ruby/
31
- def eql? other
39
+ def eql?(other)
32
40
  self.class == other.class && self == other
33
41
  end
34
42
 
35
43
  # Generates hash of slug in order to allow two records of the same type and
36
44
  # id to work with something like:
37
45
  #
38
- # [ Film.new('ABC'), Film.new('DEF') ] & [ Film.new('DEF'), Film.new('GHI') ]
39
- # #=> [ Film.new('DEF') ]
46
+ # [ Film.new('AB'), Film.new('EF') ] & [ Film.new('EF'), Film.new('GH') ]
47
+ # #=> [ Film.new('EF') ]
40
48
  #
41
49
  # @return [Integer] hash of slug
42
50
  # @note Guided by http://woss.name/2011/01/20/equality-comparison-and-ordering-in-ruby/
43
51
  def hash
44
- self.slug.hash
52
+ slug.hash
53
+ end
54
+
55
+ private
56
+
57
+ def self.cinema_page(cinema_id)
58
+ @cinema_page ||= PicturehouseUk::Internal::CinemaPage.new(cinema_id)
45
59
  end
46
60
  end
47
61
  end
@@ -0,0 +1,72 @@
1
+ module PicturehouseUk
2
+ # @api private
3
+ module Internal
4
+ # Parses a chunk of HTML to derive address
5
+ class AddressParser
6
+ # CSS for address lines
7
+ ADDRESS_LINES_CSS = '.cinemaListBox'
8
+
9
+ # regular expression for postal code
10
+ POSTCODE_REGEX = /[A-Z]{1,2}\d{1,2}[A-Z]?\s\d{1,2}[A-Z]{1,2}/
11
+
12
+ # @param [String] node the HTML to parse into an address
13
+ # @return [PicturehouseUk::Internal::AddressParser]
14
+ def initialize(html)
15
+ @html = html
16
+ end
17
+
18
+ # @return [Hash] contains :street_address, :extended_address, :locality,
19
+ # :postal_code, :country
20
+ # @note Uses the address naming from http://microformats.org/wiki/adr
21
+ def address
22
+ {
23
+ street_address: array[0],
24
+ extended_address: array.length > 3 ? array[1] : nil,
25
+ locality: array[-2],
26
+ postal_code: array[-1],
27
+ country: 'United Kingdom'
28
+ }
29
+ end
30
+
31
+ private
32
+
33
+ def array
34
+ @array ||= begin
35
+ if standard?
36
+ lines[0..postal_code_index(lines)]
37
+ else
38
+ # this is a horrendous hack for Hackney Picturehouse
39
+ doc.css('p').to_s.split('Box Office')[0].split('<br> ')[1..-1]
40
+ end
41
+ end
42
+ end
43
+
44
+ def doc
45
+ @doc ||= Nokogiri::HTML(@html)
46
+ end
47
+
48
+ def matched_lines
49
+ @matched_lines ||= begin
50
+ matched = doc.css(ADDRESS_LINES_CSS).map { |n| n.children[0].to_s }
51
+ matched.reject { |e| e == '' }
52
+ end
53
+ end
54
+
55
+ def postal_code_index(array)
56
+ array.index { |element| element.match(POSTCODE_REGEX) }
57
+ end
58
+
59
+ def lines
60
+ if matched_lines.length > 0 && matched_lines[0].match(/\d+\Z/) # komedia
61
+ ["#{matched_lines[0]} #{matched_lines[1]}"] + matched_lines[2..-1]
62
+ else
63
+ matched_lines
64
+ end
65
+ end
66
+
67
+ def standard?
68
+ lines && lines.length > 0
69
+ end
70
+ end
71
+ end
72
+ end