ndd-url_checker 0.1.1 → 0.2.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.
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