deferred_exception 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2d06b37f13627db3218a4ee56857298de1f3a55d
4
+ data.tar.gz: bfa53bcf72cd17287592042b5083eaea28af880d
5
+ SHA512:
6
+ metadata.gz: 11684832cbd0259c401cf0b4759d0b20e5da08f97481baf265ed273f750402b8a2b419462fa9c5479f65b1e18906d81a8ff1b25a360f09cc4a5a1bafd01261c9
7
+ data.tar.gz: a001aac8c73da616bde363b58359d1d7aa2d345157a50f31e664b4f781c1fb232d171b90e99965402d1845917a0b3c8317ea7a2e7ddaee9cb3e1b6a99e94e306
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p247
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - '1.9.3'
4
+ - '1.9.2'
5
+ - '2.0.0'
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in deferred_exception.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ deferred_exception (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.0.9)
10
+ method_source (0.8.2)
11
+ pry (0.9.12.2)
12
+ coderay (~> 1.0.5)
13
+ method_source (~> 0.8)
14
+ slop (~> 3.4)
15
+ rake (10.1.0)
16
+ slop (3.4.6)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 1.3)
23
+ deferred_exception!
24
+ pry
25
+ rake
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 sonnym
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Deferred Exception
2
+
3
+ [![Build Status](https://travis-ci.org/sonnym/deferred_exception.png?branch=master)](https://travis-ci.org/sonnym/deferred_exception)
4
+ [![Code Climate](https://codeclimate.com/github/sonnym/deferred_exception.png)](https://codeclimate.com/github/sonnym/deferred_exception)
5
+
6
+ Have you ever found yourself writing code like this? Have you presumed that you
7
+ would notice a problem and go looking in your logs to find the problem?
8
+
9
+ ```ruby
10
+ class EmailBlaster
11
+ def self.process_all!
12
+ all.each { |email| email.blast! }
13
+ end
14
+
15
+ def blast!
16
+ begin
17
+ # do some atomic work here
18
+ rescue StandardError => e
19
+ Logger.debug("Something went wrong #{e.message}")
20
+ end
21
+ end
22
+
23
+ # &c.
24
+ end
25
+ ```
26
+
27
+ Wouldn't it be nice, nay preferable, to accrue exceptions without stopping the
28
+ subsequent atomic operations?
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ gem 'deferred_exception'
35
+
36
+ And then execute:
37
+
38
+ $ bundle
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install deferred_exception
43
+
44
+ ## Usage
45
+
46
+ Deferred Exception adds a `defer_exceptions` method to the `Enumerable` module
47
+ that wraps the enumberable object and stores any exceptions that are raised
48
+ during iteration.
49
+
50
+ ```ruby
51
+ class EmailBlaster
52
+ def self.process_all!
53
+ all.defer_exceptions.each do { |email| email.blast! }
54
+ end
55
+
56
+ def blast!
57
+ # important, atomic work here
58
+ end
59
+ end
60
+ ```
61
+
62
+ Any exceptions will be caught and queued into a `ExceptionSet` class, a
63
+ subclass of `StandardError` and will be raised once the iteration is complete.
64
+ `ExceptionSet#message` will be a string containing messages and backtraces from
65
+ all caught exceptions
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib/deferred_exception'
8
+ t.test_files = FileList['test/lib/deferred_exception/*_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'deferred_exception/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'deferred_exception'
8
+ spec.version = DeferredException::VERSION
9
+ spec.authors = ['sonnym']
10
+ spec.email = ['michaud.sonny@gmail.com']
11
+ spec.description = 'Collect exceptions rather than exiting early when enumerating atomic operations.'
12
+ spec.summary = spec.description
13
+ spec.homepage = 'https://github.com/sonnym/deferred_exception'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'pry'
24
+ end
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,9 @@
1
+ require_relative 'deferred_exception/version'
2
+ require_relative 'deferred_exception/enumerator'
3
+ require_relative 'deferred_exception/exception_set'
4
+
5
+ module Enumerable
6
+ def defer_exceptions
7
+ DeferredException::Enumerator.new(self)
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ module DeferredException
2
+ class Enumerator
3
+ include Enumerable
4
+
5
+ attr_accessor :enumerator
6
+
7
+ def initialize(enumerator)
8
+ self.enumerator = enumerator
9
+ end
10
+
11
+ def each(&block)
12
+ enumerator.each do |item|
13
+ begin
14
+ block.call(item)
15
+ rescue StandardError => e
16
+ exceptions.push(e)
17
+ end
18
+ end
19
+
20
+ unless exceptions.empty?
21
+ raise DeferredException::ExceptionSet.new(exceptions)
22
+ end
23
+
24
+ enumerator
25
+ end
26
+
27
+ def exceptions
28
+ @exceptions ||= []
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module DeferredException
2
+ class ExceptionSet < StandardError
3
+ attr_accessor :exceptions
4
+
5
+ def initialize(exceptions)
6
+ self.exceptions = exceptions
7
+ end
8
+
9
+ def message
10
+ exceptions.map { |exception| individual_message(exception) }.join("\n#{'=' * 5}\n")
11
+ end
12
+
13
+ private
14
+ def individual_message(exception)
15
+ "#{exception.message}#{"\n#{exception.backtrace.join("\n")}" unless exception.backtrace.nil?}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module DeferredException
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe DeferredException do
4
+ it 'should create a #defer_exceptions method' do
5
+ assert_respond_to [], :defer_exceptions
6
+ end
7
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe DeferredException::Enumerator do
4
+ it 'is an enumerable' do
5
+ enumerator = DeferredException::Enumerator.new([:foo, :bar, :baz])
6
+ assert_kind_of Enumerable, enumerator
7
+ end
8
+
9
+ it 'returns the original enumerable after processing' do
10
+ original = [:foo, :bar, :baz]
11
+ enumerator = DeferredException::Enumerator.new(original)
12
+ assert_equal original, enumerator.each {}
13
+ end
14
+
15
+ it 'raises ExceptionSet if exceptions occur' do
16
+ items = [-> { raise StandardError(:foo) },
17
+ -> { raise StandardError(:bar) },
18
+ -> { raise StandardError(:baz) }]
19
+
20
+ enumerator = DeferredException::Enumerator.new(items)
21
+
22
+ assert_raises(DeferredException::ExceptionSet) do
23
+ enumerator.each { |fn| fn.call }
24
+ end
25
+ end
26
+
27
+ it 'contiues processing elements after an exception is encountered' do
28
+ mock = MiniTest::Mock.new
29
+ mock.expect(:bar, true)
30
+
31
+ items = [-> { raise StandardError(:foo) },
32
+ -> { mock.send(:bar) }]
33
+
34
+
35
+ enumerator = DeferredException::Enumerator.new(items)
36
+
37
+ begin
38
+ enumerator.each { |fn| fn.call }
39
+ rescue
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,15 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe DeferredException::ExceptionSet do
4
+ it 'should return a compound message' do
5
+ exceptions = [StandardError.new('foo'), StandardError.new('bar')]
6
+ exception_set = DeferredException::ExceptionSet.new(exceptions)
7
+ assert_equal "foo\n=====\nbar", exception_set.message
8
+ end
9
+
10
+ it 'should return a compound message' do
11
+ exceptions = [StandardError.new('foo'), StandardError.new('bar')]
12
+ exception_set = DeferredException::ExceptionSet.new(exceptions)
13
+ assert_equal "foo\n=====\nbar", exception_set.message
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'pry'
3
+
4
+ require File.expand_path('../../lib/deferred_exception.rb', __FILE__)
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deferred_exception
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - sonnym
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Collect exceptions rather than exiting early when enumerating atomic
56
+ operations.
57
+ email:
58
+ - michaud.sonny@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .ruby-version
64
+ - .travis.yml
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - deferred_exception.gemspec
71
+ - deferred_exception/.gitignore
72
+ - lib/deferred_exception.rb
73
+ - lib/deferred_exception/enumerator.rb
74
+ - lib/deferred_exception/exception_set.rb
75
+ - lib/deferred_exception/version.rb
76
+ - test/lib/deferred_exception/deferred_exception_test.rb
77
+ - test/lib/deferred_exception/enumerator_test.rb
78
+ - test/lib/deferred_exception/exception_set.rb
79
+ - test/test_helper.rb
80
+ homepage: https://github.com/sonnym/deferred_exception
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.0.3
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Collect exceptions rather than exiting early when enumerating atomic operations.
104
+ test_files:
105
+ - test/lib/deferred_exception/deferred_exception_test.rb
106
+ - test/lib/deferred_exception/enumerator_test.rb
107
+ - test/lib/deferred_exception/exception_set.rb
108
+ - test/test_helper.rb