ndd-url_checker 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ffa576d85139cd2300b55ba9c340fdda8608850
4
- data.tar.gz: 58835f36306bd29f9375f0f6c65afc7045b7e411
3
+ metadata.gz: 99d36713ad66fe4e91a94f8244232de75f4c9e2c
4
+ data.tar.gz: 49b3313cc7ef54b102f1af8a2e921f9b96e5c70e
5
5
  SHA512:
6
- metadata.gz: 84a715175f934072d1b5ec7244302d4c8385d7db3d724d1ac7596e9e98ca00f58bccf12f68c4d88ef4cac4fb865f7ea192f435bcc939783e0dd8a4fcec77281b
7
- data.tar.gz: 62ee300dbe403c80a42e8387dc79657549c9bbf0f0be3d3788ed692d2847517bc70ecd460a130be42517d6086b909885b7e47dc29c48c79f72e5ab0eebb80e37
6
+ metadata.gz: eb756c557e6c76cb1f5ba947b383e3b3a5baec440f7b4ae1763251744fb925050a5724588d779ea51f1901948abf2777c77bd5f86c57734117a533794144a7b6
7
+ data.tar.gz: 3d1aa11d6dec0ea8159bb643b6cebe52f33d84b979e0f2bd858356085a616e5c170af888e72cb8f5872a0617421c0e34541b5ace207e12eaf7ff537a6d3e1727
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
- # NDD URL Checker changelog
1
+ # NDD URL Checker changelog
2
+
3
+ ## Version 0.2.0
4
+
5
+ - Switched to named parameters
6
+ - Fixed documentation
7
+ - Removed the `UrlChecker#validate` method.
8
+ - Changed the type of the return value of `UrlChecker#check`.
2
9
 
3
10
  ## Version 0.1.0
4
11
 
5
- * initial commit
12
+ - initial commit
data/Guardfile CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  # ----------------------------------------------------------------------------------------------------------------------
3
2
  # bundler
4
3
  # ----------------------------------------------------------------------------------------------------------------------
@@ -31,6 +30,7 @@ guard :rspec, cmd: 'bundle exec rspec' do
31
30
 
32
31
  # ----- lib directory
33
32
  watch(%r{^lib/(.+)\.rb$}) { |m| %W(spec/#{m[1]}_spec.rb) }
33
+ watch(%r{^lib/(.+)\.(.+)\.erb$}) { |m| %W(spec/#{m[1]}_spec.rb) }
34
34
 
35
35
  # ----- spec directory
36
36
  watch(%r{^spec/.+_spec\.rb$})
data/README.md CHANGED
@@ -5,13 +5,73 @@
5
5
  [![Code Climate](https://codeclimate.com/github/ddidier/ndd-url_checker/badges/gpa.svg)](https://codeclimate.com/github/ddidier/ndd-url_checker)
6
6
  [![Test Coverage](https://codeclimate.com/github/ddidier/ndd-url_checker/badges/coverage.svg)](https://codeclimate.com/github/ddidier/ndd-url_checker)
7
7
 
8
- URL validator.
8
+ An URL validator.
9
+
10
+ The API documentation can be find at [RubyDoc](http://www.rubydoc.info/github/ddidier/ndd-url_checker).
9
11
 
10
12
  ## Prerequisites
11
13
 
12
- This gem is tested with Ruby 2.1.x.
14
+ This gem requires Ruby 2.x and is tested with:
15
+
16
+ - Ruby 2.0.0
17
+ - Ruby 2.1.x
18
+
19
+ ## Usage
20
+
21
+ This gem provides several types of URL checker which may be composed using the [decorator pattern](http://en.wikipedia.org/wiki/Decorator_pattern). An URL checker exposes a [`#check(*urls)`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/AbstractUrlChecker#check-instance_method) method which has 2 variants:
22
+
23
+ - if a single URL is passed as an argument, it returns a single [`NDD::UrlChecker::Status`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/Status)
24
+ - if multiple URL are passed as arguments, it returns an array of [`NDD::UrlChecker::Status`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/Status)
25
+
26
+ A status has a code reflecting the result of the URL check. For the time being:
27
+
28
+ - valid codes are `direct` and `redirected`
29
+ - invalid codes are `failed`, `too_many_redirects` and `unknown_host`
30
+
31
+ ### BlockingUrlChecker
32
+
33
+ [`NDD::UrlChecker::BlockingUrlChecker`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/BlockingUrlChecker) provides a serial URL checker using the standard [`Net:HTTP`](http://ruby-doc.org/stdlib-2.1.5/libdoc/net/http/rdoc/Net/HTTP.html) implementation.
34
+
35
+ ```ruby
36
+ checker = NDD::UrlChecker::BlockingUrlChecker.new
37
+
38
+ status = checker.check('http://www.invalid123456789.com/')
39
+ status.valid? # => false
40
+ status.code # => :unknown_host
41
+
42
+ status = checker.check('http://www.google.com/')
43
+ status.valid? # => true
44
+ status.code # => :direct
45
+
46
+ statuses = checker.check('http://www.invalid123456789.com/', 'http://www.google.com/')
47
+ statuses[0].uri # => 'http://www.invalid123456789.com/'
48
+ statuses[0].valid? # => false
49
+ statuses[0].code # => :unknown_host
50
+ statuses[1].uri # => 'http://www.google.com/'
51
+ statuses[1].valid? # => true
52
+ statuses[1].code # => :direct
53
+ ```
54
+
55
+ ### ParallelUrlChecker
56
+
57
+ But this will be very time consuming if there is a lot of URL to check. Meet [`NDD::UrlChecker::ParallelUrlChecker`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/ParallelUrlChecker) which enables a very significant processing boost. For the time being, only a forked implementation is provided but a threaded one is planed.
58
+
59
+ ```ruby
60
+ checker = NDD::UrlChecker::ParallelUrlChecker.new(parallelism: 100)
61
+ checker.check('http://www.invalid123456789.com/')
62
+ checker.check('http://www.google.com/')
63
+ ```
64
+
65
+ ### ReportingUrlChecker
66
+
67
+ For a nice looking report, use [`NDD::UrlChecker::ReportingUrlChecker`](http://www.rubydoc.info/github/ddidier/ndd-url_checker/NDD/UrlChecker/ReportingUrlChecker) which enables reporting capabilities using ERB templates. Several built-in templates are provided: CSV (planed), HTML and JSON (planed).
13
68
 
14
- ## TODO
69
+ ```ruby
70
+ checker = NDD::UrlChecker:: ReportingUrlChecker.new(delegate_checker)
71
+ statuses = checker.check('http://www.invalid123456789.com/', 'http://www.google.com/')
72
+ report_as_text = checker.report(:html, '/some/report.html')
73
+ report_as_text = checker.report('/some/template.erb', '/some/report.html')
74
+ ```
15
75
 
16
76
  ## Copyright
17
77
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -4,27 +4,18 @@ module NDD
4
4
  module UrlChecker
5
5
 
6
6
  # Abstract class, not very ruby-ish :)
7
+ # @abstract
7
8
  # @author David DIDIER
8
9
  class AbstractUrlChecker
9
10
 
10
- # Checks that the given URL are valid.
11
- # If there is only a single URL parameter, returns a NDD::UrlChecker::Status.
12
- # If there is only multiple URL parameters, returns a Hash of NDD::UrlChecker::Status indexed by their URI.
13
- # @param urls [String|Array<String>] the URLs to check.
14
- # @return [NDD::UrlChecker::Status|Hash<String => NDD::UrlChecker::Status>]
11
+ # Checks that the given URLs are valid.
12
+ # @param urls [String, Array<String>] the URLs to check
13
+ # @return [NDD::UrlChecker::Status, Array<NDD::UrlChecker::Status>] a single status for a single URL, an array
14
+ # of status for multiple parameters
15
15
  def check(*urls)
16
16
  raise 'NDD::UrlChecker::UrlChecker#check must be implemented'
17
17
  end
18
18
 
19
- # Validates that the given URL are valid.
20
- # If there is only a single URL parameter, returns a boolean.
21
- # If there is only multiple URL parameters, returns a Hash of boolean indexed by their URI.
22
- # @param urls [String|Array<String>] the URLs to validate.
23
- # @return [NDD::UrlChecker::Status|Hash<String => Boolean>]
24
- def validate(*urls)
25
- raise 'NDD::UrlChecker::UrlChecker#validate must be implemented'
26
- end
27
-
28
19
  end
29
20
  end
30
21
  end
@@ -7,47 +7,36 @@ require 'net/https'
7
7
  module NDD
8
8
  module UrlChecker
9
9
 
10
- # An URL checker using the blocking Net::HTTP class.
10
+ # An URL checker using the blocking {Net::HTTP} class.
11
11
  # @author David DIDIER
12
12
  class BlockingUrlChecker < AbstractUrlChecker
13
13
 
14
14
  # Create a new instance.
15
- # @param [Fixnum] maximum_redirects the maximum number of redirects before failing.
16
- # @param [Fixnum] timeout the number of seconds to wait before failing.
17
- def initialize(maximum_redirects=5, timeout=5)
15
+ # @param maximum_redirects [Fixnum] the maximum number of redirects to follow before failing.
16
+ # @param timeout [Fixnum] the number of seconds to wait before failing.
17
+ def initialize(maximum_redirects: 5, timeout: 5)
18
18
  @logger = Logging.logger[self]
19
19
  @maximum_redirects = maximum_redirects
20
20
  @timeout = timeout
21
21
  end
22
22
 
23
- # Checks that the given URL are valid.
24
- # If there is only a single URL parameter, returns a NDD::UrlChecker::Status.
25
- # If there is only multiple URL parameters, returns a Hash of NDD::UrlChecker::Status indexed by their URI.
26
- # @param [String|Array<String>] urls
27
- # @return [NDD::UrlChecker::Status|Hash<String => NDD::UrlChecker::Status>]
23
+ # Checks that the given URLs are valid.
24
+ # @param urls [String, Array<String>] the URLs to check
25
+ # @return [NDD::UrlChecker::Status, Array<NDD::UrlChecker::Status>] a single status for a single URL, an array
26
+ # of status for multiple parameters
28
27
  def check(*urls)
29
28
  @logger.info "Checking #{urls.size} URL(s)"
30
- return check_single(urls.first) if urls.size == 1
31
- Hash[urls.map { |url| [url, check_single(url)] }]
32
- end
33
-
34
- # Validates that the given URL are valid.
35
- # If there is only a single URL parameter, returns a boolean.
36
- # If there is only multiple URL parameters, returns a Hash of boolean indexed by their URI.
37
- # @param [String|Array<String>] urls
38
- # @return [NDD::UrlChecker::Status|Hash<String => Boolean>]
39
- def validate(*urls)
40
- @logger.info "Validating #{urls.size} URL(s)"
41
- return validate_single(urls.first) if urls.size == 1
42
- Hash[urls.map { |url| [url, validate_single(url)] }]
29
+ return check_single(urls.first) if urls.size < 2
30
+ urls.map { |url| check_single(url) }
43
31
  end
44
32
 
45
33
 
34
+ # -------------------------------------------------------------------------------------------------- private -----
46
35
  private
47
36
 
48
37
  # Checks that the given URL is valid.
49
- # @param [String] url
50
- # @return [NDD::UrlChecker::Status]
38
+ # @param url [String] the URL to check
39
+ # @return [NDD::UrlChecker::Status]
51
40
  def check_single(url)
52
41
  begin
53
42
  @logger.debug "Checking: #{url}"
@@ -63,18 +52,10 @@ module NDD
63
52
  status
64
53
  end
65
54
 
66
- # Validates that the given URL are valid.
67
- # @param [String] url
68
- # @return [Boolean]
69
- def validate_single(url)
70
- @logger.debug "Validating: #{url}"
71
- check_single(url).valid?
72
- end
73
-
74
- # Checks that the given URL is valid.
75
- # @param [URI::HTTP] uri the URI to check
76
- # @param [NDD::UrlChecker::Status] status the current status of the stack
77
- # @return [NDD::UrlChecker::Status]
55
+ # Checks that the given URI is valid.
56
+ # @param uri [URI::HTTP] the URI to check.
57
+ # @param status [NDD::UrlChecker::Status] the current status of the stack.
58
+ # @return [NDD::UrlChecker::Status]
78
59
  def check_uri(uri, status)
79
60
  if status.uris.size() > @maximum_redirects
80
61
  return status.too_many_redirects
@@ -122,7 +103,7 @@ module NDD
122
103
  end
123
104
  end
124
105
 
125
- # FIXME: platform dependent?
106
+ # FIXME: platform dependent?
126
107
  UNKNOWN_HOST_MESSAGE = 'getaddrinfo: Name or service not known'
127
108
 
128
109
  def unknown_host?(error)
@@ -9,49 +9,43 @@ module NDD
9
9
 
10
10
  # An URL checker using forks to parallelize processing. To be used with MRI.
11
11
  # @author David DIDIER
12
+ # @attr_reader delegate [#check] the delegate URL checker.
13
+ # @attr_reader parallelism [Fixnum] the number of processes.
12
14
  class ForkedUrlChecker < AbstractUrlChecker
13
15
 
14
16
  attr_reader :delegate
15
17
  attr_reader :parallelism
16
18
 
17
19
  # Create a new instance.
18
- # @param [AbstractUrlChecker] delegate_checker defaults to {NDD::UrlChecker::BlockingUrlChecker}.
19
- # @param [Fixnum] parallelism the number of processes.
20
- def initialize(delegate_checker=nil, parallelism=10)
20
+ # @param delegate_checker [AbstractUrlChecker] defaults to {NDD::UrlChecker::BlockingUrlChecker}.
21
+ # @param parallelism [Fixnum] the number of processes.
22
+ def initialize(delegate_checker: nil, parallelism: 10)
21
23
  @logger = Logging.logger[self]
22
24
  @delegate = delegate_checker || BlockingUrlChecker.new
23
25
  @parallelism = parallelism
24
26
  end
25
27
 
28
+ # Checks that the given URLs are valid.
29
+ # @param urls [String, Array<String>] the URLs to check
30
+ # @return [NDD::UrlChecker::Status, Array<NDD::UrlChecker::Status>] a single status for a single URL, an array
31
+ # of status for multiple parameters
26
32
  def check(*urls)
27
33
  return delegate.check(*urls) if urls.size < 2
28
- process(urls, :check)
29
- end
30
-
31
- def validate(*urls)
32
- return delegate.validate(*urls) if urls.size < 2
33
- process(urls, :validate)
34
- end
35
-
36
34
 
37
- private
38
-
39
- def process(urls, method)
40
35
  # for receiving results
41
36
  result_pipe = Cod.pipe
42
37
  # partition the URLs, but not too much :)
43
38
  url_slices = partition(urls, [parallelism, urls.size].min)
44
39
  # and distribute them among the workers
45
40
  pids = url_slices.each_with_index.map do |url_slice, index|
46
- fork { Worker.new(index, result_pipe, delegate).send(method, url_slice) }
41
+ fork { Worker.new(index, result_pipe, delegate).check(url_slice) }
47
42
  end
48
43
 
49
44
  # read back the results
50
- results = urls.reduce({}) do |hash, _|
45
+ results = urls.map do |_|
51
46
  result = result_pipe.get
52
- hash.merge!(result)
53
47
  @logger.debug("Processed URLs #{hash.size}/#{urls.size}")
54
- hash
48
+ result
55
49
  end
56
50
 
57
51
  # kill all the workers
@@ -60,9 +54,15 @@ module NDD
60
54
  results
61
55
  end
62
56
 
63
- # Evenly distributes data into buckets. For example:
64
- #  partition([1, 2, 3], 2) => [[1, 3], [2]]
65
- #  partition([1, 2, 3, 4, 5, 6], 3) => [[1, 4], [2, 5], [3, 6]]
57
+
58
+ # -------------------------------------------------------------------------------------------------- private -----
59
+ private
60
+
61
+ # Evenly distributes data into buckets.
62
+ #
63
+ # @example
64
+ # partition([1, 2, 3], 2) #=> [[1, 3], [2]]
65
+ # partition([1, 2, 3, 4, 5, 6], 3) #=> [[1, 4], [2, 5], [3, 6]]
66
66
  def partition(data, buckets)
67
67
  Array.new.tap do |slices|
68
68
  buckets.times.each { |_| slices << Array.new }
@@ -71,7 +71,9 @@ module NDD
71
71
  end
72
72
 
73
73
 
74
+ # ---------------------------------------------------------------------------------------------------- class -----
74
75
  # A simple worker class processing URL one by one.
76
+ # @private
75
77
  class Worker
76
78
  def initialize(id, result_pipe, url_checker)
77
79
  @logger = Logging.logger[self]
@@ -83,18 +85,12 @@ module NDD
83
85
  def check(urls)
84
86
  @logger.debug("[worker #{@id}] Checking #{urls.size} URLs")
85
87
  urls.each do |url|
86
- @result_pipe.put({url => @url_checker.check(url)})
87
- end
88
- end
89
-
90
- def validate(urls)
91
- @logger.debug("[worker #{@id}] Validating #{urls.size} URLs")
92
- urls.each do |url|
93
- @result_pipe.put({url => @url_checker.validate(url)})
88
+ @result_pipe.put(@url_checker.check(url))
94
89
  end
95
90
  end
96
91
  end
97
92
 
93
+ private_constant :Worker
98
94
  end
99
95
  end
100
96
  end
@@ -7,39 +7,40 @@ require 'ndd/url_checker/threaded_url_checker'
7
7
  module NDD
8
8
  module UrlChecker
9
9
 
10
- # Wraps an instance of ThreadedUrlChecker or ForkedUrlChecker
11
- # depending of the underlying Ruby implementation.
10
+ # Wraps an instance of {NDD::UrlChecker::ThreadedUrlChecker} or {NDD::UrlChecker::ForkedUrlChecker}
11
+ # depending of the underlying Ruby implementation.
12
12
  # @author David DIDIER
13
+ # @attr_reader delegate [#check] the delegate URL checker.
13
14
  class ParallelUrlChecker < AbstractUrlChecker
14
15
 
15
16
  attr_reader :delegate
16
17
 
17
18
  # Create a new instance.
18
- # @param [AbstractUrlChecker] delegate_checker defaults to {NDD::UrlChecker::BlockingUrlChecker}.
19
- # @param [Fixnum] parallelism the number of threads or processes.
20
- def initialize(delegate_checker=nil, parallelism=10)
19
+ # @param delegate_checker [AbstractUrlChecker] defaults to {NDD::UrlChecker::BlockingUrlChecker}.
20
+ # @param parallelism [Fixnum] the number of threads or processes.
21
+ def initialize(delegate_checker: nil, parallelism: 10)
21
22
  @logger = Logging.logger[self]
22
23
 
23
24
  @logger.debug "Ruby engine is #{RUBY_ENGINE}"
24
25
  if RUBY_ENGINE == 'jruby'
25
26
  @logger.info 'Creating a threaded URL checker'
26
- parallel_checker = ThreadedUrlChecker.new(delegate_checker, parallelism)
27
+ parallel_checker = ThreadedUrlChecker.new(delegate_checker: delegate_checker, parallelism: parallelism)
27
28
  else
28
29
  @logger.info 'Creating a forked URL checker'
29
- parallel_checker = ForkedUrlChecker.new(delegate_checker, parallelism)
30
+ parallel_checker = ForkedUrlChecker.new(delegate_checker: delegate_checker, parallelism: parallelism)
30
31
  end
31
32
 
32
33
  @delegate = parallel_checker
33
34
  end
34
35
 
36
+ # Checks that the given URLs are valid.
37
+ # @param urls [String, Array<String>] the URLs to check
38
+ # @return [NDD::UrlChecker::Status, Array<NDD::UrlChecker::Status>] a single status for a single URL, an array
39
+ # of status for multiple parameters
35
40
  def check(*urls)
36
41
  @delegate.check(*urls)
37
42
  end
38
43
 
39
- def validate(*urls)
40
- @delegate.validate(*urls)
41
- end
42
-
43
44
  end
44
45
  end
45
46
  end
@@ -0,0 +1,97 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
7
+ <style>
8
+ body {
9
+ padding: 1em;
10
+ }
11
+ </style>
12
+
13
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
14
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
15
+ <script language="JavaScript">
16
+ $(document).ready(function() {
17
+ $('input[type=radio][name=urlsFilter]').change(function() {
18
+ if (this.value == 'all') {
19
+ $('tr').show();
20
+ }
21
+ else if (this.value == 'invalid') {
22
+ $('tr').not('.danger').hide();
23
+ }
24
+ });
25
+ });
26
+ </script>
27
+ </head>
28
+
29
+ <body>
30
+
31
+ <h1>URL Checker Report</h1>
32
+
33
+ <table class="table table-condensed table-hover" style="width: auto">
34
+ <tbody>
35
+ <tr>
36
+ <td>User CPU time</td>
37
+ <td><%= benchmark.utime %> second(s)</td>
38
+ </tr>
39
+ <tr>
40
+ <td>System CPU time</td>
41
+ <td><%= benchmark.stime %> second(s)</td>
42
+ </tr>
43
+ <tr>
44
+ <td>Total time</td>
45
+ <td><%= benchmark.total %> second(s)</td>
46
+ </tr>
47
+ <tr>
48
+ <td>Elapsed real time</td>
49
+ <td><%= benchmark.real %> second(s)</td>
50
+ </tr>
51
+ <tr>
52
+ <td>Number of URLs</td>
53
+ <td><%= results.size %></td>
54
+ </tr>
55
+ <tr>
56
+ <td>Average time for 1 URL</td>
57
+ <td><%= benchmark.real/results.size %> second(s)</td>
58
+ </tr>
59
+ </tbody>
60
+ </table>
61
+
62
+ <div class="radio">
63
+ <label>
64
+ <input type="radio" name="urlsFilter" id="showAllUrls" value="all" checked="true" />
65
+ Show all URLs
66
+ </label>
67
+ </div>
68
+ <div class="radio">
69
+ <label>
70
+ <input type="radio" name="urlsFilter" id="showInvalidUrls" value="invalid" />
71
+ Show invalid URLs
72
+ </label>
73
+ </div>
74
+
75
+ <table class="table table-condensed table-hover" style="width: auto">
76
+ <thead>
77
+ <tr>
78
+ <th>#</th>
79
+ <th>URL</th>
80
+ <th>Result</th>
81
+ <th>Comment</th>
82
+ </tr>
83
+ </thead>
84
+ <tbody>
85
+ <% results.each_with_index do |status, index| %>
86
+ <tr class="<%= status.invalid? ? 'danger' : '' %>">
87
+ <td><%= index+1 %></td>
88
+ <td><a href="<%= status.uri %>" target="_blank"><%= status.uri %></a></td>
89
+ <td><%= status.class %></td>
90
+ <td><% if status.invalid? %><%= status.error %><% end %></td>
91
+ </tr>
92
+ <% end %>
93
+ </tbody>
94
+ </table>
95
+
96
+ </body>
97
+ </html>
@@ -0,0 +1,83 @@
1
+ require 'benchmark'
2
+ require 'erb'
3
+ require 'logging'
4
+ require 'ndd/url_checker'
5
+ require 'ostruct'
6
+
7
+ module NDD
8
+ module UrlChecker
9
+
10
+ # Wraps an instance of URL checker and provides reporting capabilities using ERB templates.
11
+ # @author David DIDIER
12
+ # @attr_reader delegate [#check] the delegate URL checker.
13
+ class ReportingUrlChecker < AbstractUrlChecker
14
+
15
+ attr_reader :delegate
16
+
17
+ # Create a new instance.
18
+ # @param delegate_checker [AbstractUrlChecker].
19
+ def initialize(delegate_checker)
20
+ @logger = Logging.logger[self]
21
+ @delegate = delegate_checker
22
+ end
23
+
24
+ def check(*urls)
25
+ results = nil
26
+ benchmark = Benchmark.measure { results = @delegate.check(*urls) }
27
+ @logger.debug "Checking #{urls.size} URL(s) benchmark: #{benchmark}"
28
+
29
+ if urls.size > 1
30
+ @context = OpenStruct.new(
31
+ {
32
+ benchmark: benchmark,
33
+ results: results.sort_by { |status| status.uri }
34
+ })
35
+ else
36
+ @context = OpenStruct.new(
37
+ {
38
+ benchmark: benchmark,
39
+ results: [results]
40
+ })
41
+ end
42
+
43
+ results
44
+ end
45
+
46
+ # Creates a report about the previous check using the specified template. The result may be written to a file.
47
+ # @param template [Symbol, String] a predefined template (:csv, :html, :json) or the path of a template file.
48
+ # @param output_path [String, nil] the path of the output file.
49
+ # @return [String] the report.
50
+ def report(template, output_path=nil)
51
+ template_path = template_path(template)
52
+ template_content = ERB.new(File.new(template_path).read)
53
+ report = template_content.result(@context.instance_eval { binding })
54
+
55
+ if output_path
56
+ @logger.info "Reporting to #{output_path}"
57
+ File.open(output_path, 'w') { |file| file.write(report) }
58
+ end
59
+
60
+ report
61
+ end
62
+
63
+
64
+ # -------------------------------------------------------------------------------------------------- private -----
65
+ private
66
+
67
+ def template_path(symbol_or_path)
68
+ case symbol_or_path
69
+ when :csv then
70
+ # File.expand_path(File.join(File.dirname(__FILE__), 'reporting_url_checker.csv.erb'))
71
+ raise 'TODO'
72
+ when :html then
73
+ File.expand_path(File.join(File.dirname(__FILE__), 'reporting_url_checker.html.erb'))
74
+ when :json then
75
+ # File.expand_path(File.join(File.dirname(__FILE__), 'reporting_url_checker.json.erb'))
76
+ raise 'TODO'
77
+ else
78
+ symbol_or_path
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end