beer_in_the_evening 0.0.3 → 0.0.4

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.
data/README.md CHANGED
@@ -9,6 +9,7 @@ Wrong.
9
9
 
10
10
  require 'beer_in_the_evening'
11
11
  search = BeerInTheEvening::Search.new
12
+ search.maximum_results = 10
12
13
  search.tube_station = BeerInTheEvening::Location::Tube::HOLBORN
13
14
  search.minimum_rating = 6
14
15
  search.real_ale = true
@@ -18,6 +19,7 @@ Wrong.
18
19
  random_pub.to_s
19
20
  # => "Lord Clyde, 2.2 miles, 6.7 / 10, http://beerintheevening.com/pubs/s/65/6501/Lord_Clyde/Canonbury"
20
21
 
22
+ There are a few more examples in the `examples/` directory.
21
23
 
22
24
  ## Authors
23
25
 
@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  s.add_runtime_dependency "nokogiri"
22
+ s.add_runtime_dependency "null_logger"
22
23
  end
@@ -0,0 +1,15 @@
1
+ require 'beer_in_the_evening'
2
+ require 'logger'
3
+
4
+ STDOUT.sync = true
5
+ logger = Logger.new STDOUT
6
+ search = BeerInTheEvening::Search.new :logger => logger
7
+ search.tube_station = BeerInTheEvening::Location::Tube::HOLBORN
8
+ search.maximum_results = 5
9
+ search.minimum_rating = 6
10
+ search.real_ale = true
11
+ search.wifi = true
12
+ search.food = true
13
+ search.each do |pub|
14
+ puts pub.to_s
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'beer_in_the_evening'
2
+ require 'logger'
3
+
4
+ STDOUT.sync = true
5
+ logger = Logger.new STDOUT
6
+ search = BeerInTheEvening::Search.new :logger => logger
7
+ search.postcode = 'SE1 1EY'
8
+ search.maximum_results = 5
9
+ search.minimum_rating = 6
10
+ search.wifi = true
11
+ search.each do |pub|
12
+ puts pub.to_s
13
+ end
@@ -1,33 +1,45 @@
1
1
  module BeerInTheEvening
2
2
  class Pub
3
+ attr_accessor :data
4
+ private :data=
5
+
3
6
  def initialize data
4
- @data = data
7
+ self.data = data
8
+ end
9
+
10
+ def distance_known?
11
+ !distance.nil?
5
12
  end
6
13
 
7
14
  def name
8
- @data.css("td b a:first-child")[0].inner_text.to_s
15
+ data.css("td b a:first-child")[0].inner_text.to_s.strip
9
16
  end
10
17
 
11
18
  def url
12
- "http://beerintheevening.com" + @data.css("td b a:first-child")[0]['href'].to_s
19
+ "http://beerintheevening.com" + self.data.css("td b a:first-child")[0]['href'].to_s
13
20
  end
14
21
 
15
- def rating
16
- results = @data.css("td:nth-child(3)")[0].inner_text.scan /Rating:(.*)\/10/
17
- results[0][0].to_f if results[0]
22
+ def rating_column
23
+ distance_known? ? 3 : 2
18
24
  end
19
25
 
20
- def visited?
21
- Meetup.exists? self
26
+ def rating
27
+ results = data.css("td:nth-child(#{rating_column})")[0].inner_text.scan /Rating:(.*)\/10/
28
+ results[0][0].to_f if results[0]
22
29
  end
23
30
 
24
31
  def distance
25
- results = @data.css("td:nth-child(2)")[0].inner_text.scan /Distance:(.*)miles/
32
+ results = data.css("td:nth-child(2)")[0].inner_text.scan /Distance:(.*)miles/
26
33
  results[0][0].to_f if results[0]
34
+ rescue
27
35
  end
28
36
 
29
37
  def to_s
30
- [ name, "#{distance} miles", "#{rating} / 10", url ].join ', '
38
+ if distance_known?
39
+ [ name, "#{distance} miles", "#{rating} / 10", url ]
40
+ else
41
+ [ name, "#{rating} / 10", url ]
42
+ end.join ', '
31
43
  end
32
44
  end
33
45
  end
@@ -1,11 +1,26 @@
1
1
  module BeerInTheEvening
2
2
  class Search
3
+ class << self
4
+ attr_accessor :maximum_cache_ttl
5
+ end
6
+ # Invalidate the cache at least every 28 days
7
+ self.maximum_cache_ttl = 86400 * 28
8
+
9
+ attr_accessor :postcode
3
10
  attr_accessor :tube_station
4
11
  attr_accessor :real_ale
5
12
  attr_accessor :food
6
13
  attr_accessor :wifi
7
14
  attr_accessor :minimum_rating
8
15
 
16
+ attr_accessor :maximum_results
17
+
18
+ attr_accessor :logger
19
+
20
+ def initialize options = {}
21
+ self.logger = options[:logger] || NullLogger.instance
22
+ end
23
+
9
24
  def number_of_results
10
25
  matches = page(0).to_s.scan /showing \d+ to \d+ of (\d+)/
11
26
  matches[0][0].to_i
@@ -13,18 +28,36 @@ module BeerInTheEvening
13
28
 
14
29
  def each &block
15
30
  current_page = 0
31
+ results_total = 0
16
32
  loop do
33
+ logger.debug "Finding next set of results"
17
34
  results = results_on_page current_page
18
35
  break if results.empty?
36
+ if maximum_results
37
+ while results_total + results.size > maximum_results do
38
+ logger.debug "Trimming results. Max = #{maximum_results}, Current = #{results_total + results.size}"
39
+ results.pop
40
+ end
41
+ end
42
+ logger.debug "Yielding #{results.size} pubs to client"
19
43
  results.each &block
44
+ logger.debug "Client code finished"
20
45
  current_page += 1
46
+ results_total += results.size
47
+ break if maximum_results && results_total >= maximum_results
21
48
  end
22
49
  end
23
50
  include Enumerable
24
51
 
52
+ def escaped_postcode
53
+ CGI.escape postcode
54
+ end
55
+ private :escaped_postcode
56
+
25
57
  def query_string
26
58
  params = []
27
59
  params << "tu=#{tube_station}" if tube_station
60
+ params << "postcode=#{escaped_postcode}" if postcode
28
61
  params << "ra=on" if real_ale
29
62
  params << "f=on" if food
30
63
  params << "wireless=on" if wifi
@@ -35,30 +68,54 @@ module BeerInTheEvening
35
68
 
36
69
  def page n
37
70
  uri = "http://www.beerintheevening.com/pubs/results.shtml?#{query_string}&page=#{n}"
71
+ logger.debug "Page #{n} of results will be at #{uri}"
38
72
  content = read_cache uri do
73
+ logger.debug "Fetching #{uri}"
39
74
  open(uri).read
40
75
  end
76
+ logger.debug "Building document from HTML data"
41
77
  doc = Nokogiri::HTML content
42
78
  end
43
79
  private :page
44
80
 
81
+ def cache_generation
82
+ Time.now.to_i / self.class.maximum_cache_ttl.to_i
83
+ end
84
+ private :cache_generation
85
+
86
+ def cache_prefix
87
+ "beer_in_the_evening-#{BeerInTheEvening::VERSION}-#{self.class.maximum_cache_ttl.to_i}-#{cache_generation}"
88
+ end
89
+ private :cache_prefix
90
+
45
91
  def read_cache uri
46
- cache_dir = Dir.tmpdir + "/beer_in_the_evening-#{BeerInTheEvening::VERSION}"
92
+ cache_dir = Dir.tmpdir + "/#{cache_prefix}"
47
93
  Dir.mkdir cache_dir unless File.exists? cache_dir
48
94
  cache_file_name = "#{cache_dir}/#{Digest::SHA1.hexdigest(uri)}.html"
49
- return File.read(cache_file_name) if File.exists? cache_file_name
95
+ if File.exists? cache_file_name
96
+ logger.debug "Found #{uri} in cache at #{cache_file_name}"
97
+ return File.read cache_file_name
98
+ end
99
+ logger.debug "Did not find #{uri} in cache"
50
100
  data = yield
101
+ logger.debug "Data is #{data.bytesize}b"
102
+ logger.debug "Adding #{uri} to cache as #{cache_file_name}"
51
103
  File.open cache_file_name, 'w+' do |f|
52
104
  f.puts data
53
105
  end
106
+ logger.debug "Returning data"
54
107
  data
55
108
  end
56
109
  private :read_cache
57
110
 
58
111
  def results_on_page n
59
- page(n).css('table.pubtable tr.pubtable').to_a.map { |row|
112
+ rows = page(n).css('table.pubtable tr.pubtable').to_a
113
+ logger.debug "Found #{rows.size} results on page #{n}"
114
+ rows.map! { |row|
60
115
  Pub.new row
61
116
  }
117
+ logger.debug "Returning results as pubs"
118
+ rows
62
119
  end
63
120
  private :results_on_page
64
121
  end
@@ -1,3 +1,3 @@
1
1
  module BeerInTheEvening
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -2,6 +2,8 @@ require "nokogiri"
2
2
  require "open-uri"
3
3
  require "digest/sha1"
4
4
  require "tmpdir"
5
+ require "null_logger"
6
+ require "cgi"
5
7
 
6
8
  require "beer_in_the_evening/version"
7
9
  require "beer_in_the_evening/pub"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beer_in_the_evening
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-01 00:00:00.000000000Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &70318119693620 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,28 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70318119693620
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: null_logger
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
25
46
  description: Search over the Beer In The Evening site looking for suitable pubs
26
47
  email:
27
48
  - craig@barkingiguana.com
@@ -34,6 +55,8 @@ files:
34
55
  - README.md
35
56
  - Rakefile
36
57
  - beer_in_the_evening.gemspec
58
+ - examples/near_holborn.rb
59
+ - examples/near_postcode.rb
37
60
  - lib/beer_in_the_evening.rb
38
61
  - lib/beer_in_the_evening/location/dlr.rb
39
62
  - lib/beer_in_the_evening/location/tube.rb
@@ -60,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
83
  version: '0'
61
84
  requirements: []
62
85
  rubyforge_project: beer_in_the_evening
63
- rubygems_version: 1.8.10
86
+ rubygems_version: 1.8.24
64
87
  signing_key:
65
88
  specification_version: 3
66
89
  summary: Is it pub time?