picturehouse_uk 1.0.2 → 2.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 (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