execute_with_rescue_with_airbrake 0.0.1

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: a075f476d5e0d9f96a18858757b1f0f967162c8e
4
+ data.tar.gz: 57fe7504b06259d529e6a56cc4910ac91728ad25
5
+ SHA512:
6
+ metadata.gz: da8223cb3c1484790c8d9a883faf00f705d572aef2f74c81886ff18e7914d0c0efeb912b2f42a40bda49684be01ea517c08fc7748a480bcf101c308a8648c5d2
7
+ data.tar.gz: 204f405743ecb2ae9e20d55b3482429383e0d0d443c1281a802325a96016a8c24f430f20bc3392ceb261b52e9ea63538dc0b24d6a0dba647e965c1fc6d8ee848
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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
18
+ *.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ cache:
3
+ - bundler
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.0
8
+ - 2.1.1
9
+ gemfile:
10
+ - gemfiles/rails_3_2.gemfile
11
+ - gemfiles/rails_4_0.gemfile
12
+ - gemfiles/rails_4_1.gemfile
data/Appraisals ADDED
@@ -0,0 +1,11 @@
1
+ appraise "rails-3-2" do
2
+ gem "activesupport", "3.2.17"
3
+ end
4
+
5
+ appraise "rails-4-0" do
6
+ gem "activesupport", "4.0.4"
7
+ end
8
+
9
+ appraise "rails-4-1" do
10
+ gem "activesupport", "4.1.0.rc1"
11
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ### Changelog
2
+
3
+
4
+ - **0.0.1**
5
+ - Initial Release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in execute_with_rescue_with_airbrake.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 PikachuEXE
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,101 @@
1
+ # ExecuteWithRescueWithAirbrake
2
+
3
+ TODO: Write a gem description
4
+
5
+ The Airbrake adapter plus mixin to be used with `execute_with_rescue`.
6
+
7
+ ## Support
8
+ ===========
9
+ Tested against:
10
+ - Active Support of version `3.2`, `4.0` and `4.1` (pre-3.2 got wrong dependency & I don't want to support)
11
+ - MRI `1.9.3`, `2.0.0`, `2.1.0`, `2.1.1`
12
+
13
+ [![Build Status](http://img.shields.io/travis/PikachuEXE/execute_with_rescue_with_airbrake.svg)](https://travis-ci.org/PikachuEXE/execute_with_rescue_with_airbrake)
14
+ [![Gem Version](http://img.shields.io/gem/v/execute_with_rescue_with_airbrake.svg)](http://badge.fury.io/rb/execute_with_rescue_with_airbrake)
15
+ [![Dependency Status](http://img.shields.io/gemnasium/PikachuEXE/execute_with_rescue_with_airbrake.svg)](https://gemnasium.com/PikachuEXE/execute_with_rescue_with_airbrake)
16
+ [![Coverage Status](http://img.shields.io/coveralls/PikachuEXE/execute_with_rescue_with_airbrake.svg)](https://coveralls.io/r/PikachuEXE/execute_with_rescue_with_airbrake)
17
+ [![Code Climate](http://img.shields.io/codeclimate/github/PikachuEXE/execute_with_rescue_with_airbrake.svg)](https://codeclimate.com/github/PikachuEXE/execute_with_rescue_with_airbrake)
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'execute_with_rescue_with_airbrake'
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install execute_with_rescue_with_airbrake
32
+
33
+ ## Usage
34
+
35
+ TODO: Write usage instructions here
36
+
37
+ Note: You must configurate `airbrake` first or you won't be able to send anything (I have to do the same in `spec_helper`)
38
+
39
+ ### `include ExecuteWithRescue::Mixins::WithAirbrake`
40
+ Once inlcuded, `rescue_from StandardError, with: :notify_by_airbrake_or_raise` will be called.
41
+
42
+
43
+ ### `#set_default_airbrake_notice_error_class`, `#set_default_airbrake_notice_error_message`, `#add_default_airbrake_notice_parameters`
44
+ **Private** methods to be called within a block in `execute_with_rescue`
45
+ Every `execute_with_rescue` call will push a new airbrake adapater for the instance (with before hook),
46
+ so you can have different custom error class, message or/and parameters within the same service/worker class.
47
+ You should call these methods within the block passed to `execute_with_rescue`, as there is no adapter from the beginning.
48
+
49
+ Here is an example for getting a document from the network:
50
+ ```ruby
51
+ class SomeServiceClass
52
+
53
+ BadNetworkConnectionError = Class.new(StandardError)
54
+
55
+ include ExecuteWithRescue::Mixins::WithAirbrake
56
+
57
+ # then run code with possible errors
58
+ def perform(url_of_webpage)
59
+ execute_with_rescue do
60
+ set_default_airbrake_notice_error_class(BadNetworkConnectionError)
61
+ set_default_airbrake_notice_error_message("We have a bad network today...")
62
+ add_default_airbrake_notice_parameters({url_of_webpage: url_of_webpage})
63
+
64
+ # Calling `add_default_airbrake_notice_parameters` with duplicated key(s) would raise error
65
+ # add_default_airbrake_notice_parameters({url_of_webpage: something_else}) =>
66
+ # ExecuteWithRescueWithAirbrake::Adapters::AirbrakeAdapter::Errors::ParameterKeyConflict
67
+
68
+ doc = Nokogiri::HTML(open(listing_url))
69
+ end
70
+ end
71
+ end
72
+ ```
73
+
74
+ ### `#notify_by_airbrake_or_raise`
75
+ **Private** method to be called automatically by `rescue_from StandardError` from the mixin.
76
+ Call this if you have some custom handling for some error classes
77
+ Override this if you have some additional operation like logging for all kinds of error inherited from `StandardError`
78
+ Note: It would re-raise the exception if `airbrake` would ignore all notify call in that environment (see `development_environments` in its config).
79
+ Example:
80
+ ```ruby
81
+ class SomeWorker
82
+ rescue_from ActiveRecord::RecordInvalid,
83
+ with: :notify_by_airbrake_or_raise_ar_invalid_error
84
+
85
+ def notify_by_airbrake_or_raise_ar_invalid_error(ex)
86
+ add_default_airbrake_notice_parameters({
87
+ active_record_instance: ex.record.inspect,
88
+ active_record_instance_errors: ex.record.errors.inspect,
89
+ })
90
+ notify_by_airbrake_or_raise(ex)
91
+ end
92
+ end
93
+ ```
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it ( http://github.com/PikachuEXE/execute_with_rescue_with_airbrake/fork )
98
+ 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin feature/my-new-feature`)
101
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+
5
+ require "rspec/core/rake_task"
6
+ require "appraisal"
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
11
+ task :default do
12
+ sh "rake appraisal:install && rake appraisal spec"
13
+ end
14
+ else
15
+ task :default => :spec
16
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'execute_with_rescue_with_airbrake/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "execute_with_rescue_with_airbrake"
8
+ spec.version = ExecuteWithRescueWithAirbrake::VERSION
9
+ spec.authors = ["PikachuEXE"]
10
+ spec.email = ["pikachuexe@gmail.com"]
11
+ spec.summary = %q{The Airbrake adapter plus mixin to be used with `execute_with_rescue`}
12
+ spec.homepage = "http://github.com/PikachuEXE/execute_with_rescue_with_airbrake"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "execute_with_rescue", "~> 0.0", ">= 0.0.1"
21
+ spec.add_dependency "airbrake", "~> 3.1.0"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "appraisal", ">= 0.5.2"
26
+ spec.add_development_dependency "rspec", "~> 2.14.0"
27
+ spec.add_development_dependency "coveralls", ">= 0.7"
28
+ spec.add_development_dependency "gem-release", ">= 0.7"
29
+
30
+ spec.required_ruby_version = ">= 1.9.3"
31
+
32
+ spec.required_rubygems_version = ">= 1.4.0"
33
+ end
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "3.2.17"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "4.0.4"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "4.1.0.rc1"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,13 @@
1
+ module ExecuteWithRescue
2
+ module Errors
3
+ class NoAirbrakeAdapter < RuntimeError
4
+ def self.new(msg = nil)
5
+ msg ||= <<-ERR_MSG
6
+ There is no airbrake adapter available.
7
+ Maybe you forgot to use `execute_with_rescue`?
8
+ ERR_MSG
9
+ super(msg)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,66 @@
1
+ require 'airbrake'
2
+ require 'active_support/concern'
3
+ require 'active_support/core_ext/module/delegation'
4
+
5
+ require 'execute_with_rescue'
6
+ require 'execute_with_rescue/errors/no_airbrake_adapter'
7
+ require 'execute_with_rescue_with_airbrake/adapters/airbrake_adapter'
8
+
9
+ module ExecuteWithRescue
10
+ module Mixins
11
+ module WithAirbrake
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ include ExecuteWithRescue::Mixins::Core
16
+
17
+ add_execute_with_rescue_before_hook do
18
+ _execute_with_rescue_airbrake_adapters
19
+ .push(ExecuteWithRescueWithAirbrake::Adapters::AirbrakeAdapter.new)
20
+ end
21
+ add_execute_with_rescue_after_hook do
22
+ _execute_with_rescue_airbrake_adapters.pop
23
+ end
24
+
25
+ rescue_from StandardError,
26
+ with: :notify_by_airbrake_or_raise
27
+
28
+ delegate :set_default_airbrake_notice_error_class,
29
+ :set_default_airbrake_notice_error_message,
30
+ :add_default_airbrake_notice_parameters,
31
+ to: :_execute_with_rescue_current_airbrake_adapter
32
+ end
33
+
34
+ # Call this if you have some custom handling for some classes
35
+ # Override this if you have some additional operation like logging
36
+ # for all kinds of error inherited from `StandardError`
37
+ #
38
+ # @example Add default parameters when rescuing AR Invalid Error
39
+ # class SomeWorker
40
+ # rescue_from ActiveRecord::RecordInvalid,
41
+ # with: :notify_by_airbrake_or_raise_ar_invalid_error
42
+ #
43
+ # def notify_by_airbrake_or_raise_ar_invalid_error(ex)
44
+ # add_default_airbrake_notice_parameters({
45
+ # active_record_instance: ex.record.inspect,
46
+ # active_record_instance_errors: ex.record.errors.inspect,
47
+ # })
48
+ # notify_by_airbrake_or_raise(ex)
49
+ # end
50
+ # end
51
+ def notify_by_airbrake_or_raise(ex)
52
+ _execute_with_rescue_current_airbrake_adapter
53
+ .notify_or_raise(ex)
54
+ end
55
+
56
+ # For pushing and popping the adapters
57
+ def _execute_with_rescue_airbrake_adapters
58
+ @_execute_with_rescue_airbrake_adapters ||= []
59
+ end
60
+ def _execute_with_rescue_current_airbrake_adapter
61
+ _execute_with_rescue_airbrake_adapters.last ||
62
+ (raise ExecuteWithRescue::Errors::NoAirbrakeAdapter)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,7 @@
1
+ require 'execute_with_rescue_with_airbrake/version'
2
+ require 'execute_with_rescue'
3
+ require 'execute_with_rescue/mixins/with_airbrake'
4
+
5
+
6
+ module ExecuteWithRescueWithAirbrake
7
+ end
@@ -0,0 +1,123 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+
3
+ module ExecuteWithRescueWithAirbrake
4
+ module Adapters
5
+ class AirbrakeAdapter
6
+ module Errors
7
+ InvalidParameters = Class.new(ArgumentError)
8
+ ParameterKeyConflict = Class.new(ArgumentError)
9
+ end
10
+
11
+ # This should NOT be used directly, but used with rescue_from
12
+ # if you need custom options use Airbrake directly
13
+ #
14
+ # @param ex [Exception]
15
+ # The exception rescued
16
+ #
17
+ # @raise [Exception] the original exception
18
+ # when Airbrake detects the current environment is not public
19
+ # @see should_raise?
20
+ def notify_or_raise(ex)
21
+ if should_raise?
22
+ raise ex
23
+ else
24
+ notify_or_ignore_with_options(ex)
25
+ end
26
+ end
27
+
28
+
29
+ # set the default `error_class` option when notify by Airbrake
30
+ # It must can be init without argument, this method won't check it
31
+ # Pass nil to clear it
32
+ #
33
+ # @param message [NilClass, Class]
34
+ # the error message to be used in Airbrake notice
35
+ #
36
+ # @raise [ArgumentError] when class is not nil or symbol
37
+ def set_default_airbrake_notice_error_class(klass)
38
+ (klass.nil? || klass.is_a?(Class)) or raise ArgumentError
39
+
40
+ @default_airbrake_notice_error_class = klass
41
+ end
42
+
43
+ # set the default `error_message` option when notify by Airbrake
44
+ # Pass nil to clear it
45
+ #
46
+ # @param message [NilClass, String]
47
+ # the error message to be used in Airbrake notice
48
+ #
49
+ # @raise [ArgumentError] when message is not nil or string
50
+ def set_default_airbrake_notice_error_message(message)
51
+ (message.nil? || message.is_a?(String)) or raise ArgumentError
52
+
53
+ @default_airbrake_notice_error_message = message
54
+ end
55
+
56
+ # Push new default `parameters` option when notify by Airbrake
57
+ # Pass nil to clear it
58
+ #
59
+ # @param new_params [Hash]
60
+ # the additional parameters to be used in Airbrake notice
61
+ #
62
+ # @raise [InvalidParameters]
63
+ # when new_params is not hash
64
+ # @raise [ParameterKeyConflict]
65
+ # when new_params contains keys conflicting with existing keys
66
+ def add_default_airbrake_notice_parameters(new_params)
67
+ new_params.is_a?(Hash) or
68
+ (raise Errors::InvalidParameters)
69
+ new_params =
70
+ new_params.with_indifferent_access
71
+
72
+ # find out common element size (which should be 0)
73
+ common_keys =
74
+ default_airbrake_notice_parameters.keys &
75
+ new_params.keys
76
+ if common_keys.size > 0
77
+ raise Errors::ParameterKeyConflict,
78
+ "Conflicting keys: #{common_keys.inspect}"
79
+ end
80
+
81
+ default_airbrake_notice_parameters.merge!(new_params)
82
+ end
83
+
84
+ private
85
+
86
+ def notify_or_ignore_with_options(ex)
87
+ Airbrake.notify_or_ignore(ex, build_notice_options)
88
+ end
89
+
90
+ def build_notice_options
91
+ result_options_hash = Hash.new
92
+
93
+ if @default_airbrake_notice_error_class
94
+ result_options_hash[:error_class] =
95
+ @default_airbrake_notice_error_class
96
+ end
97
+ if @default_airbrake_notice_error_message
98
+ result_options_hash[:error_message] =
99
+ @default_airbrake_notice_error_message
100
+ end
101
+ unless default_airbrake_notice_parameters.empty?
102
+ result_options_hash[:parameters] =
103
+ default_airbrake_notice_parameters.symbolize_keys
104
+ end
105
+
106
+ result_options_hash
107
+ end
108
+
109
+ def default_airbrake_notice_parameters
110
+ @default_airbrake_notice_parameters ||= HashWithIndifferentAccess.new
111
+ end
112
+
113
+ # @return [Boolean]
114
+ # Whether the adapter should raise the error instead
115
+ # (like in development or test)
116
+ #
117
+ # @see Airbrake.configuration.development_environments
118
+ def should_raise?
119
+ !Airbrake.configuration.public?
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,3 @@
1
+ module ExecuteWithRescueWithAirbrake
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe ExecuteWithRescue::Mixins::WithAirbrake do
5
+ let(:test_class) { TestServiceWithAirbrake }
6
+ let(:test_class_instance) { test_class.new }
7
+ let(:call_service) { test_class_instance.call }
8
+
9
+ shared_context 'when airbrake adapter assumed exists' do
10
+ let(:adapter_class) do
11
+ ExecuteWithRescueWithAirbrake::Adapters::AirbrakeAdapter
12
+ end
13
+ let!(:adapter_instance) { adapter_class.new }
14
+ before do
15
+ # Avoid Error
16
+ test_class_instance
17
+ .stub(:_execute_with_rescue_current_airbrake_adapter)
18
+ .and_return(adapter_instance)
19
+ end
20
+ end
21
+
22
+ describe 'included modules' do
23
+ subject { test_class.ancestors }
24
+
25
+ it {should include ExecuteWithRescue::Mixins::Core}
26
+ it {should include ExecuteWithRescue::Mixins::WithAirbrake}
27
+ end
28
+
29
+ describe 'call delegated methods' do
30
+ context 'without calling #execute_with_rescue' do
31
+ let(:test_class) { TestServiceWithAirbrakeWithoutExecuteWithRescueCall }
32
+ let(:expected_error_class) { ExecuteWithRescue::Errors::NoAirbrakeAdapter }
33
+
34
+ specify do
35
+ expect{ call_service }
36
+ .to raise_error(expected_error_class)
37
+ end
38
+ end
39
+ context 'without calling #execute_with_rescue' do
40
+ let(:test_class) { TestServiceWithAirbrakeWithExecuteWithRescueCall }
41
+
42
+ specify do
43
+ expect{ call_service }
44
+ .to_not raise_error
45
+ end
46
+ end
47
+ context 'with calling #execute_with_rescue'
48
+ end
49
+
50
+ describe 'delegation' do
51
+ include_context 'when airbrake adapter assumed exists'
52
+
53
+ before { adapter_instance.stub(method_name) }
54
+
55
+ let(:send_message) { test_class_instance.send(method_name) }
56
+
57
+ shared_examples_for 'delegation' do
58
+ specify do
59
+ expect(adapter_instance).to receive(method_name)
60
+
61
+ send_message
62
+ end
63
+ end
64
+
65
+ describe 'for #set_default_airbrake_notice_error_class' do
66
+ let(:method_name) { :set_default_airbrake_notice_error_class }
67
+
68
+ it_behaves_like 'delegation'
69
+ end
70
+ describe 'for #set_default_airbrake_notice_error_message' do
71
+ let(:method_name) { :set_default_airbrake_notice_error_message }
72
+
73
+ it_behaves_like 'delegation'
74
+ end
75
+ describe 'for #add_default_airbrake_notice_parameters' do
76
+ let(:method_name) { :add_default_airbrake_notice_parameters }
77
+
78
+ it_behaves_like 'delegation'
79
+ end
80
+ end
81
+
82
+ describe 'execution' do
83
+ include_context 'when airbrake adapter assumed exists'
84
+
85
+ before { Airbrake.configuration.stub(public?: true) }
86
+
87
+ describe 'when there is no error raised' do
88
+ specify do
89
+ expect(Airbrake)
90
+ .to_not receive(:notify_or_ignore)
91
+
92
+ call_service
93
+ end
94
+ end
95
+ describe 'when there is error raised' do
96
+ context 'and it is a standard error' do
97
+ let(:test_class) { TestServiceWithAirbrakeWithError }
98
+
99
+ specify do
100
+ expect(Airbrake)
101
+ .to(receive(:notify_or_ignore)
102
+ .with(kind_of(StandardError), {}))
103
+
104
+ call_service
105
+ end
106
+ end
107
+
108
+ describe 'setting custom airbrake options' do
109
+ let(:test_class) { TestServiceWithAirbrakeWithErrorAndAirbrakeOption }
110
+
111
+ specify do
112
+ expect(Airbrake)
113
+ .to(receive(:notify_or_ignore)
114
+ .with(kind_of(StandardError), {
115
+ error_class: test_class::CustomError,
116
+ error_message: 'hi',
117
+ parameters: {
118
+ foo: :bar
119
+ },
120
+ }))
121
+
122
+ call_service
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe ExecuteWithRescueWithAirbrake::Adapters::AirbrakeAdapter do
5
+ let!(:instance) { described_class.new }
6
+
7
+ let!(:notice_options) do
8
+ {parameters: {}}
9
+ end
10
+ let!(:exception_rescued) { StandardError.new('hi I am test error') }
11
+
12
+ let(:notify_or_raise) { instance.notify_or_raise(exception_rescued) }
13
+
14
+ #before { }
15
+
16
+ context 'when exception should not be notified according to Airbrake' do
17
+ before { Airbrake.configuration.stub(public?: false) }
18
+
19
+ it 're-raise the rescue error' do
20
+ expect { notify_or_raise }.to raise_error(exception_rescued.class,
21
+ exception_rescued.message)
22
+ end
23
+ end
24
+ context 'when exception should be notified according to Airbrake' do
25
+ before { Airbrake.configuration.stub(public?: true) }
26
+
27
+ it 'does not re-raise the rescued error' do
28
+ expect { notify_or_raise }.to_not raise_error
29
+ end
30
+ end
31
+
32
+ context 'assuming Airbrake says it error should be notified' do
33
+ before { Airbrake.configuration.stub(public?: true) }
34
+
35
+ it 'calls Airbrake.notify_or_ignore' do
36
+ Airbrake.should_receive(:notify_or_ignore)
37
+
38
+ notify_or_raise
39
+ end
40
+
41
+
42
+ describe '#set_default_airbrake_notice_error_class' do
43
+ let(:set_error_class) do
44
+ instance.set_default_airbrake_notice_error_class(
45
+ default_error_class)
46
+ end
47
+ let(:default_error_class) { nil }
48
+ let(:option_key) { :error_class }
49
+
50
+ before do
51
+ # Return the options only
52
+ Airbrake.stub(:notify_or_ignore) {|*args| args.last }
53
+ end
54
+ let(:options_hash) { notify_or_raise }
55
+ subject { options_hash }
56
+
57
+ context 'when its not called' do
58
+ its(:keys) { should_not include(option_key) }
59
+ end
60
+ context 'when its called with nil' do
61
+ let(:default_error_class) { nil }
62
+ before { set_error_class }
63
+
64
+ its(:keys) { should_not include(option_key) }
65
+ end
66
+ context 'when its called with custom error' do
67
+ let(:default_error_class) { ArgumentError }
68
+ before { set_error_class }
69
+
70
+ it { should include({option_key => default_error_class}) }
71
+ end
72
+ end
73
+
74
+ describe '#set_default_airbrake_notice_error_message' do
75
+ let(:set_error_message) do
76
+ instance.set_default_airbrake_notice_error_message(
77
+ default_error_message)
78
+ end
79
+ let(:default_error_message) { nil }
80
+ let(:option_key) { :error_message }
81
+
82
+ before do
83
+ # Return the options only
84
+ Airbrake.stub(:notify_or_ignore) {|*args| args.last }
85
+ end
86
+ let(:options_hash) { notify_or_raise }
87
+ subject { options_hash }
88
+
89
+ context 'when its not called' do
90
+ its(:keys) { should_not include(option_key) }
91
+ end
92
+ context 'when its called with nil' do
93
+ let(:default_error_message) { nil }
94
+ before { set_error_message }
95
+
96
+ its(:keys) { should_not include(option_key) }
97
+ end
98
+ context 'when its called with custom error' do
99
+ let(:default_error_message) { 'hello' }
100
+ before { set_error_message }
101
+
102
+ it { should include({option_key => default_error_message}) }
103
+ end
104
+ end
105
+
106
+ describe '#add_default_airbrake_notice_parameters' do
107
+ # Must defined as method or it won't run twice
108
+ def add_parameters(params = new_parameters)
109
+ instance.add_default_airbrake_notice_parameters(
110
+ params)
111
+ end
112
+ let(:new_parameters) { Hash.new }
113
+ let(:option_key) { :parameters }
114
+
115
+ before do
116
+ # Return the options only
117
+ Airbrake.stub(:notify_or_ignore) {|*args| args.last }
118
+ end
119
+ let(:options_hash) { notify_or_raise }
120
+ let(:parameters_hash) { options_hash[option_key] }
121
+
122
+ subject { options_hash }
123
+
124
+ context 'when its not called' do
125
+ its(:keys) { should_not include(option_key) }
126
+ end
127
+ context 'when its called with non hash' do
128
+ let(:new_parameters) { Array.new }
129
+ let(:expected_error_class) do
130
+ described_class::Errors::InvalidParameters
131
+ end
132
+
133
+ specify do
134
+ expect { add_parameters }
135
+ .to raise_error(expected_error_class)
136
+ end
137
+ end
138
+ context 'when its called with empty hash' do
139
+ let(:new_parameters) { Hash.new }
140
+ before { add_parameters }
141
+
142
+ its(:keys) { should_not include(option_key) }
143
+ end
144
+
145
+ context 'when its called with non-empty hash' do
146
+ subject { parameters_hash }
147
+
148
+ let(:new_parameters) { {foo: :bar} }
149
+
150
+ context 'and there is no conflicting key' do
151
+ before { add_parameters }
152
+
153
+ it { should include(new_parameters) }
154
+ end
155
+
156
+ context 'and there is a conflicting key' do
157
+ before { add_parameters }
158
+ let(:expected_error_class) do
159
+ described_class::Errors::ParameterKeyConflict
160
+ end
161
+
162
+ context 'in symbol' do
163
+ specify do
164
+ expect { add_parameters }
165
+ .to raise_error(expected_error_class)
166
+ end
167
+ end
168
+ context 'in string' do
169
+ specify do
170
+ expect { add_parameters(new_parameters.stringify_keys) }
171
+ .to raise_error(expected_error_class)
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+
179
+ describe 'options passed' do
180
+ context 'when nothing is set' do
181
+ specify do
182
+ expect(Airbrake)
183
+ .to(receive(:notify_or_ignore)
184
+ .with(kind_of(StandardError), {}))
185
+
186
+ notify_or_raise
187
+ end
188
+ end
189
+ context 'when all things are set' do
190
+ let!(:custom_error_class) { Class.new(StandardError) }
191
+ let!(:custom_error_message) { 'hi' }
192
+ let!(:custom_parameters) { {foo: :bar}.stringify_keys }
193
+ before { instance.set_default_airbrake_notice_error_class(custom_error_class) }
194
+ before { instance.set_default_airbrake_notice_error_message(custom_error_message) }
195
+ before { instance.add_default_airbrake_notice_parameters(custom_parameters) }
196
+
197
+ specify do
198
+ expect(Airbrake)
199
+ .to(receive(:notify_or_ignore)
200
+ .with(kind_of(StandardError), {
201
+ error_class: custom_error_class,
202
+ error_message: custom_error_message,
203
+ parameters: custom_parameters.symbolize_keys,
204
+ }))
205
+
206
+ notify_or_raise
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,51 @@
1
+
2
+ class TestServiceWithAirbrake
3
+ include ExecuteWithRescue::Mixins::WithAirbrake
4
+
5
+ def call
6
+ execute_with_rescue do
7
+ do_something
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def do_something
14
+ # do nothing
15
+ end
16
+ end
17
+
18
+ class TestServiceWithAirbrakeWithError < TestServiceWithAirbrake
19
+ def do_something
20
+ raise StandardError
21
+ end
22
+ end
23
+ class TestServiceWithAirbrakeWithErrorAndAirbrakeOption <
24
+ TestServiceWithAirbrakeWithError
25
+
26
+ CustomError = Class.new(StandardError)
27
+
28
+ def do_something
29
+ set_default_airbrake_notice_error_class(CustomError)
30
+ set_default_airbrake_notice_error_message('hi')
31
+ add_default_airbrake_notice_parameters({foo: :bar})
32
+
33
+ super
34
+ end
35
+ end
36
+
37
+ class TestServiceWithAirbrakeWithExecuteWithRescueCall <
38
+ TestServiceWithAirbrake
39
+
40
+ def do_something
41
+ set_default_airbrake_notice_error_message('test')
42
+ end
43
+ end
44
+ class TestServiceWithAirbrakeWithoutExecuteWithRescueCall <
45
+ TestServiceWithAirbrakeWithExecuteWithRescueCall
46
+
47
+ def call
48
+ # without `execute_with_rescue`
49
+ do_something
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ if ENV["TRAVIS"]
2
+ require 'coveralls'
3
+ Coveralls.wear!
4
+ end
5
+
6
+ require 'execute_with_rescue_with_airbrake'
7
+ require 'airbrake'
8
+
9
+ require 'fixtures/test_service_classes'
10
+ require 'rspec'
11
+
12
+ require 'logger'
13
+
14
+ # Need to configurate it before any `notify_or_ignore`
15
+ Airbrake.configure(true) do |config|
16
+ config.test_mode = true
17
+ end
18
+
19
+ RSpec.configure do |config|
20
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: execute_with_rescue_with_airbrake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - PikachuEXE
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: execute_with_rescue
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: airbrake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: 3.1.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 3.1.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '1.5'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: appraisal
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: 0.5.2
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: 0.5.2
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: 2.14.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 2.14.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: coveralls
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0.7'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0.7'
117
+ - !ruby/object:Gem::Dependency
118
+ name: gem-release
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0.7'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0.7'
131
+ description:
132
+ email:
133
+ - pikachuexe@gmail.com
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - .gitignore
139
+ - .rspec
140
+ - .travis.yml
141
+ - Appraisals
142
+ - CHANGELOG.md
143
+ - Gemfile
144
+ - LICENSE.txt
145
+ - README.md
146
+ - Rakefile
147
+ - execute_with_rescue_with_airbrake.gemspec
148
+ - gemfiles/rails_3_2.gemfile
149
+ - gemfiles/rails_3_2.gemfile.lock
150
+ - gemfiles/rails_4_0.gemfile
151
+ - gemfiles/rails_4_0.gemfile.lock
152
+ - gemfiles/rails_4_1.gemfile
153
+ - gemfiles/rails_4_1.gemfile.lock
154
+ - lib/execute_with_rescue/errors/no_airbrake_adapter.rb
155
+ - lib/execute_with_rescue/mixins/with_airbrake.rb
156
+ - lib/execute_with_rescue_with_airbrake.rb
157
+ - lib/execute_with_rescue_with_airbrake/adapters/airbrake_adapter.rb
158
+ - lib/execute_with_rescue_with_airbrake/version.rb
159
+ - spec/execute_with_rescue/mixins/with_airbrake_spec.rb
160
+ - spec/execute_with_rescue_with_airbrake/adapters/airbrake_adapter_spec.rb
161
+ - spec/fixtures/test_service_classes.rb
162
+ - spec/spec_helper.rb
163
+ homepage: http://github.com/PikachuEXE/execute_with_rescue_with_airbrake
164
+ licenses:
165
+ - MIT
166
+ metadata: {}
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - '>='
174
+ - !ruby/object:Gem::Version
175
+ version: 1.9.3
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '>='
179
+ - !ruby/object:Gem::Version
180
+ version: 1.4.0
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 2.2.2
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: The Airbrake adapter plus mixin to be used with `execute_with_rescue`
187
+ test_files:
188
+ - spec/execute_with_rescue/mixins/with_airbrake_spec.rb
189
+ - spec/execute_with_rescue_with_airbrake/adapters/airbrake_adapter_spec.rb
190
+ - spec/fixtures/test_service_classes.rb
191
+ - spec/spec_helper.rb
192
+ has_rdoc: