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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +18 -0
- data/README.md +7 -10
- data/Rakefile +20 -7
- data/lib/picturehouse_uk.rb +4 -1
- data/lib/picturehouse_uk/cinema.rb +51 -100
- data/lib/picturehouse_uk/film.rb +22 -8
- data/lib/picturehouse_uk/internal/address_parser.rb +72 -0
- data/lib/picturehouse_uk/internal/cinema_page.rb +35 -0
- data/lib/picturehouse_uk/internal/film_with_screenings_parser.rb +87 -37
- data/lib/picturehouse_uk/internal/title_sanitizer.rb +49 -0
- data/lib/picturehouse_uk/internal/website.rb +39 -0
- data/lib/picturehouse_uk/screening.rb +63 -19
- data/lib/picturehouse_uk/version.rb +2 -2
- data/picturehouse_uk.gemspec +11 -11
- data/test/fixture_updater.rb +43 -0
- data/test/fixtures/address-fragments/duke-of-yorks.html +39 -0
- data/test/fixtures/address-fragments/hackney-picturehouse.html +12 -0
- data/test/fixtures/cinema/Duke_Of_Yorks.html +4370 -0
- data/test/fixtures/cinema/Duke_Of_Yorks/film_last.html +45 -0
- data/test/fixtures/cinema/Duke_Of_Yorks/film_second.html +37 -0
- data/test/fixtures/{abbeygate-contact-us.html → contact_us/Duke_Of_Yorks.html} +635 -156
- data/test/fixtures/{dukes-at-komedia-contact-us.html → contact_us/Dukes_At_Komedia.html} +582 -98
- data/test/fixtures/{picturehouses-homepage.html → home.html} +642 -146
- data/test/lib/picturehouse_uk/cinema_test.rb +127 -307
- data/test/lib/picturehouse_uk/film_test.rb +65 -16
- data/test/lib/picturehouse_uk/internal/address_parser_test.rb +55 -0
- data/test/lib/picturehouse_uk/internal/cinema_page_test.rb +51 -0
- data/test/lib/picturehouse_uk/internal/film_with_screenings_parser_test.rb +44 -151
- data/test/lib/picturehouse_uk/internal/title_sanitizer_test.rb +131 -0
- data/test/lib/picturehouse_uk/internal/website_test.rb +64 -0
- data/test/lib/picturehouse_uk/screening_test.rb +149 -21
- data/test/live/integration_test.rb +68 -0
- data/test/test_helper.rb +3 -1
- metadata +40 -43
- data/test/fixtures/dukes-at-komedia-cinema.html +0 -7148
- data/test/fixtures/film_node/blue-jasmine-done.html +0 -53
- data/test/fixtures/film_node/blue-jasmine-future.html +0 -55
- data/test/fixtures/film_node/bolshoi-spartacus.html +0 -26
- data/test/fixtures/film_node/captain-phillips-with-silver-screen-and-subtitles.html +0 -103
- data/test/fixtures/film_node/fifth-estate-with-big-scream.html +0 -73
- data/test/fixtures/film_node/london-film-festival-with-toddler-time.html +0 -46
- data/test/fixtures/film_node/met-encore-rusalka-as-live.html +0 -26
- data/test/fixtures/film_node/nt-encore-hamlet.html +0 -26
- data/test/fixtures/film_node/planes-with-kids-club.html +0 -77
- data/test/fixtures/film_node/royal-opera-house-don-quixote.html +0 -26
- data/test/fixtures/film_node/rsc-encore-richard-ii.html +0 -28
- data/test/fixtures/film_node/rsc-live-richard-ii.html +0 -41
- data/test/fixtures/film_node/rsc-live-the-two-gentlemen-of-verona-zero-cert.html +0 -19
- data/test/fixtures/hackney-contact-us.html +0 -998
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 852cffd41d42e302152ccedd703e8f265b48015f
|
4
|
+
data.tar.gz: a2cfd6c6dbb93d841cc2d7c22423d9228363d342
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5da4c31df5e98af0f65e4261eca2de02da13e6f5f80ab5a75171c7b393537e801bab7740cffdfee6ce39caa6994165c3ddc4c91e28ba3f26367590c31863de3
|
7
|
+
data.tar.gz: 36e769a6373c03914f241ca65babc5e878552902627d53b6123bdc99918a605009ba0dcc41815933139c918925d7d84be828496f2dfb0853c051e9efcde3f429
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -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
|
-
#=> [
|
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.
|
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
|
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[
|
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
|
-
|
13
|
-
|
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
|
-
|
17
|
-
|
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 :
|
33
|
+
task default: :test
|
data/lib/picturehouse_uk.rb
CHANGED
@@ -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 [
|
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(
|
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 =
|
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
|
38
|
+
# # => [<PicturehouseUK::Cinema ...>, <PicturehouseUK::Cinema ...>, ...]
|
34
39
|
def self.all
|
35
|
-
cinema_links.map
|
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
|
48
|
+
# # => <PicturehouseUK::Cinema ...>
|
46
49
|
def self.find(id)
|
47
|
-
all.
|
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
|
-
# #=> {
|
56
|
-
#
|
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
|
77
|
+
# @note Uses method naming as at http://microformats.org/wiki/adr
|
75
78
|
def extended_address
|
76
|
-
|
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
|
87
|
+
# # => [<PicturehouseUk::Film ...>, <PicturehouseUk::Film ...>, ...]
|
85
88
|
def films
|
86
|
-
|
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
|
-
|
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
|
-
|
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
|
129
|
+
# # => [<PicturehouseUk::Screening ...>, <PicturehouseUk::Screening ...>]
|
130
130
|
def screenings
|
131
|
-
|
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
|
-
|
142
|
+
address[:street_address]
|
151
143
|
end
|
152
144
|
|
153
145
|
private
|
154
146
|
|
155
147
|
def self.cinema_links
|
156
|
-
|
148
|
+
home_doc.css(CINEMA_LINKS_CSS)
|
157
149
|
end
|
158
150
|
|
159
|
-
def self.
|
160
|
-
@
|
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.
|
171
|
-
|
155
|
+
def self.website
|
156
|
+
@website ||= PicturehouseUk::Internal::Website.new
|
172
157
|
end
|
173
158
|
|
174
|
-
def
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
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
|
220
|
-
@
|
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
|
data/lib/picturehouse_uk/film.rb
CHANGED
@@ -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 <=>
|
23
|
-
|
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?
|
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('
|
39
|
-
# #=> [ Film.new('
|
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
|
-
|
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
|