on_event 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.
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
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in on_event.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Brendon Murphy
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,81 @@
1
+ # OnEvent
2
+
3
+ Build callback chains for named events.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'on_event'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install on_event
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ # Regular Style:
23
+ on_event = OnEvent.new(:success, :failure)
24
+ on_event.on_success { |a| a << "A success" }
25
+ on_event.on_failure { |a| a << "A failure" }
26
+
27
+ # Block Style:
28
+ on_event = OnEvent.new(:foo, :bar) do |oe|
29
+ oe.on_foo { |a| a << "foo" }
30
+ oe.on_bar { |a| a << "bar" }
31
+ end
32
+
33
+ a = []
34
+ on_event.foo(a)
35
+ a # => ["foo",]
36
+ on_event.bar(a)
37
+ a # => ["foo", "bar"]
38
+ ```
39
+
40
+ ## Why is this useful?
41
+
42
+ You could just put event calls inline in a code block to get a similar effect.
43
+ However, in the case you want a repeatable and reusable chain of events with
44
+ shared rescue handling for firing, then this pattern helps.
45
+
46
+ An example might be you are tracking multiple metric statistics in Rails controller
47
+ actions (or via filters). Perhaps the metrics are important, but in the case of a
48
+ new user signup, not so important that you should fail the action should any of the
49
+ metrics tracking or other notifications fail.
50
+
51
+ ```ruby
52
+ on_event = OnEvent.new(:signup_success) do |oe|
53
+ oe.on_signup_success do |new_user|
54
+ Mailer.notify_admins(new_user)
55
+ end
56
+
57
+ oe.on_signup_success do |new_user|
58
+ Metrics.increment(new_user)
59
+ end
60
+ end
61
+ ```
62
+
63
+ If the admin doesn't get the email that somebody signed up, or Redis is unreachable and
64
+ your metrics are temporarily unavailable, your user still signs up.
65
+
66
+ By overriding the `#rescue_handler` in your `OnEvent` class, you can get shared exception
67
+ handling should any callback fail. This could be as simple as call to `Rails.logger.error`,
68
+ or triggering Airbrake but still swallowing the exception.
69
+
70
+ Often these callbacks are packaged into lifecycle on a model; however, it is sometimes
71
+ the case where you only want them firing in the specific context of a controller. For
72
+ instance, if I create a user on the console, I don't need to receive a mail message
73
+ about it.
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/test*.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => [:test]
@@ -0,0 +1,3 @@
1
+ class OnEvent
2
+ VERSION = "0.0.1"
3
+ end
data/lib/on_event.rb ADDED
@@ -0,0 +1,72 @@
1
+ require "on_event/version"
2
+ require 'logger'
3
+
4
+ class OnEvent
5
+ def initialize(*events)
6
+ establish_events(*events)
7
+ yield self if block_given?
8
+ end
9
+
10
+ ##
11
+ # This defines an #event_name and #on_event_name method for
12
+ # each given event. #on_event_name takes a block stored
13
+ # as a callback, which is passed the args from corresponding
14
+ # calls to #event_name
15
+ #
16
+ # # Regular Style:
17
+ # on_event = OnEvent.new(:success, :failure)
18
+ # on_event.on_success { |a| a << "A success" }
19
+ # on_event.on_failure { |a| a << "A failure" }
20
+ #
21
+ # # Block Style:
22
+ # on_event = OnEvent.new(:foo, :bar) do |oe|
23
+ # oe.on_foo { |a| a << "foo" }
24
+ # oe.on_bar { |a| a << "bar" }
25
+ # end
26
+ #
27
+ # a = []
28
+ # on_event.foo(a)
29
+ # a # => ["foo",]
30
+ # on_event.bar(a)
31
+ # a # => ["foo", "bar"]
32
+ #
33
+ def establish_events(*events)
34
+ (class << self; self; end).instance_eval do
35
+ Array(events).each do |event_name|
36
+ define_method "on_#{event_name}" do |&block|
37
+ event_blocks[event_name.to_sym] << block
38
+ end
39
+
40
+ define_method event_name do |*args|
41
+ event_blocks[event_name.to_sym].each do |block|
42
+ with_rescue { block.call *args }
43
+ end
44
+ true
45
+ end
46
+ end
47
+ end
48
+ end
49
+ alias :establish_event :establish_events
50
+
51
+ def logger
52
+ @logger ||= Logger.new(STDERR)
53
+ end
54
+
55
+ private
56
+
57
+ def event_blocks
58
+ @event_blocks ||= Hash.new {|h, k| h[k] = []}
59
+ end
60
+
61
+ def with_rescue
62
+ begin
63
+ yield
64
+ rescue => e
65
+ rescue_handler(e)
66
+ end
67
+ end
68
+
69
+ def rescue_handler(exception)
70
+ logger.error exception.message
71
+ end
72
+ end
data/on_event.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/on_event/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Brendon Murphy"]
6
+ gem.email = ["xternal1+github@gmail.com"]
7
+ gem.description = %q{Build callback chains for named events.}
8
+ gem.summary = gem.description
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.name = "on_event"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = OnEvent::VERSION
16
+ end
@@ -0,0 +1,73 @@
1
+ require "test/unit"
2
+ require File.expand_path("../../lib/on_event", __FILE__)
3
+
4
+ class TestOnEvent < Test::Unit::TestCase
5
+ def test_setup_with_no_block
6
+ subject = OnEvent.new(:foo, :bar)
7
+ assert subject.respond_to?(:on_foo)
8
+ assert subject.respond_to?(:foo)
9
+ assert subject.respond_to?(:on_bar)
10
+ assert subject.respond_to?(:bar)
11
+ end
12
+
13
+ def test_adding_event_callbacks
14
+ subject = OnEvent.new(:foo, :bar)
15
+ subject.on_foo { |a| a << "f1" }
16
+ subject.on_bar { |a| a << "b1" }
17
+ subject.on_foo { |a| a << "f2" }
18
+ subject.on_bar { |a| a << "b2" }
19
+ a = []
20
+ subject.foo(a)
21
+ subject.bar(a)
22
+ assert_equal %w[f1 f2 b1 b2], a
23
+ end
24
+
25
+ def test_callback_events_returns_true
26
+ subject = OnEvent.new(:foo)
27
+ subject.on_foo { "f1" }
28
+ assert_instance_of TrueClass, subject.foo()
29
+ end
30
+
31
+ def test_adding_establish_event_alias
32
+ subject = OnEvent.new
33
+ subject.establish_event(:foo)
34
+ assert subject.respond_to?(:on_foo)
35
+ assert subject.respond_to?(:foo)
36
+ end
37
+
38
+ def test_setup_with_block
39
+ subject = OnEvent.new(:foo, :bar) do |oe|
40
+ oe.on_foo { |a| a << "foo" }
41
+ oe.on_bar { |a| a << "bar" }
42
+ end
43
+ a = []
44
+ subject.foo(a)
45
+ subject.bar(a)
46
+ assert_equal %w[foo bar], a
47
+ end
48
+
49
+ def test_rescue_handler
50
+ subject = OnEvent.new(:foo, :bar) do |oe|
51
+ oe.on_foo { |a| a << "foo" }
52
+ oe.on_bar { |a| a << oops_missing }
53
+ oe.on_bar { |a| a << oops_another }
54
+ end
55
+
56
+ $handledExceptions = []
57
+ def subject.rescue_handler(exception)
58
+ $handledExceptions << exception.message
59
+ end
60
+
61
+ a = []
62
+ subject.foo(a)
63
+ subject.bar(a)
64
+ assert_equal ["foo"], a
65
+ assert_match /oops_missing/, $handledExceptions[0]
66
+ assert_match /oops_another/, $handledExceptions[1]
67
+ end
68
+
69
+ def test_logger
70
+ subject = OnEvent.new
71
+ assert_kind_of Logger, subject.logger
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: on_event
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Brendon Murphy
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-08-12 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Build callback chains for named events.
23
+ email:
24
+ - xternal1+github@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - lib/on_event.rb
38
+ - lib/on_event/version.rb
39
+ - on_event.gemspec
40
+ - test/test_on_event.rb
41
+ has_rdoc: true
42
+ homepage: ""
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.7
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Build callback chains for named events.
75
+ test_files:
76
+ - test/test_on_event.rb