rbevents 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 120093ba34a6948eb460635604e1bd0dcef60dcf
4
+ data.tar.gz: f213b08fd409557759a0a43b92533f48d50cadda
5
+ SHA512:
6
+ metadata.gz: 9ed412aac01a34b9c5e2a039a220910fbc34177ab6cf9810a0f85e204db42d007e62f3deb1a5354cd9e3e912abe832d069ce9d01a8dcac7df123eb7ebc79c1e8
7
+ data.tar.gz: 3a23b58dfcb8eee7da1bb0be0f6bceedc67b229eac692f6f509a7c532743c2175cddcd90b3325ca44ed83f1c8e2cc1fa51adc3765ab03f9a519992c4423bc3c9
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ rbevents
2
+ ========
3
+
4
+ It's like Observable, but better.
5
+
6
+ Example
7
+ =======
8
+ ```ruby
9
+
10
+ # Let's define a class with subscribable events
11
+ class EventsExample
12
+ include Events # Mix in the magic
13
+
14
+ # Define an event
15
+ event :activation
16
+
17
+ # Here, we define a method that fires the event
18
+ def activate
19
+ # Event.fire sets off the event and collects
20
+ # any return values from subscribed events
21
+ return_values = @activation.fire
22
+ return_values
23
+ end
24
+ end
25
+
26
+ # Let's build an object...
27
+ example = EventsExample.new
28
+
29
+ # ...and then add some subscribers
30
+ example.on_activation do
31
+ "Hello"
32
+ end
33
+ example.on_activation do
34
+ "World!"
35
+ end
36
+
37
+ # Finally, we call a method which alerts the subscribers
38
+ example.activate # => ["Hello", "World!"]
39
+ ```
40
+ Full documentation to follow!
data/lib/events.rb ADDED
@@ -0,0 +1,119 @@
1
+ # Mixin for event-driven programming.
2
+ #
3
+ # The mixin adds the following:
4
+ # - <tt>event [sym]</tt>: Creates an +Event+ with the given name
5
+ # - <tt>singleton_event [sym]</tt>: Creates a +SingleSubscriberEvent+ with the given name
6
+ # Note that the command <tt>event :abc</tt> adds an alias, <tt>on_abc</tt>, for adding event callbacks
7
+ #
8
+ # == Example
9
+ # See README
10
+ #
11
+ # == License
12
+ # If you use this, let me know? jonny.arnold89@gmail.com. Thanks.
13
+ module Events
14
+
15
+ # Version number
16
+ # Uses Semantic Versioning: http://semver.org/
17
+ VERSION = '0.1.0'
18
+
19
+ # An event that can be subscribed to,
20
+ # and runs any subscribed callback when
21
+ # it is fired.
22
+ class Event
23
+ # Gets the collection of callbacks subscribed to this event.
24
+ attr_accessor :callbacks
25
+
26
+ # Class initializer
27
+ def initialize
28
+ @callbacks = []
29
+ end
30
+
31
+ # Called when the event occurs
32
+ # [*arguments] The arguments to pass to each callback
33
+ # Returns any values returned by any subscribed callback
34
+ def fire(*arguments)
35
+ return_values = []
36
+
37
+ @callbacks.each do |proc|
38
+ return_values << proc.call(*arguments)
39
+ end
40
+
41
+ return_values
42
+ end
43
+
44
+ # Adds a callback to the event
45
+ # [proc] The block to execute
46
+ def add_callback(&proc)
47
+ @callbacks << proc
48
+ end
49
+
50
+ # Removes the given block from the event
51
+ # [proc] The block to remove
52
+ def remove_callback(&proc)
53
+ @callbacks.delete proc
54
+ end
55
+ end
56
+
57
+ # An event with a single subscriber
58
+ class SingleSubscriberEvent < Event
59
+
60
+ # Override of Event.add_callback
61
+ def add_callback(&proc)
62
+ if callbacks.length == 1
63
+ raise EventSubscriptionError, "Cannot add more than one callback to SingleSubscriberEvent"
64
+ end
65
+
66
+ super
67
+ end
68
+
69
+ # Override of Event.fire
70
+ def fire(*args)
71
+ packed_result = super
72
+ if packed_result.length == 0
73
+ return nil
74
+ else
75
+ return packed_result.first
76
+ end
77
+ end
78
+ end
79
+
80
+ # Denotes an error with event subscription
81
+ class EventSubscriptionError < StandardError
82
+ end
83
+
84
+ # :nodoc:
85
+ def self.append_features(cls)
86
+ # Create an event
87
+ # [sym] The name to assign to the event
88
+ # Retrieve via .sym
89
+ def cls.event(sym)
90
+ variable_name = "@#{sym}"
91
+
92
+ define_method(sym.to_s) do
93
+ if not instance_variable_defined? variable_name then
94
+ instance_variable_set variable_name, Event.new
95
+ end
96
+ instance_variable_get variable_name
97
+ end
98
+
99
+ firealias = "on_#{sym}"
100
+ define_method(firealias) do |&proc|
101
+ if not instance_variable_defined? variable_name then
102
+ instance_variable_set variable_name, Event.new
103
+ end
104
+ event_obj = instance_variable_get variable_name
105
+ event_obj.add_callback &proc
106
+ end
107
+ end
108
+
109
+ def cls.singleton_event(sym)
110
+ define_method(sym.to_s) do
111
+ variable_name = "@#{sym}"
112
+ if not instance_variable_defined? variable_name then
113
+ instance_variable_set variable_name, SingleSubscriberEvent.new
114
+ end
115
+ instance_variable_get variable_name
116
+ end
117
+ end
118
+ end
119
+ end
data/rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rake/testtask'
2
+ require 'rdoc/task'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/test*.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ Rake::RDocTask.new do |rd|
13
+ rd.main = "README.md"
14
+ rd.rdoc_files.include "lib/**.rb"
15
+ end
data/rbevents.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/events', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "rbevents"
7
+ gem.version = Events::VERSION
8
+ gem.summary = %q{Events for Ruby}
9
+ gem.description = %q{Provides an Event mixin for enabling classes to create events for public and private subscription.}
10
+ gem.license = "GPL"
11
+ gem.authors = ["Jonny Arnold"]
12
+ gem.email = "jonny.arnold89@gmail.com"
13
+ gem.homepage = "https://github.com/jonnyarnold/rbevents"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.0'
21
+ gem.add_development_dependency 'rake', '~> 0.8'
22
+ gem.add_development_dependency 'rdoc', '~> 3.0'
23
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
24
+ end
@@ -0,0 +1,52 @@
1
+ require "./lib/events"
2
+ require "test/unit"
3
+
4
+ class ClassWithEvents
5
+ include Events
6
+ event :test_event
7
+ singleton_event :test_singleton_event
8
+ end
9
+
10
+ class EventDrivenTest < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @test_object = ClassWithEvents.new
14
+ end
15
+
16
+ def test_can_subscribe_to_event
17
+ @test_object.test_event.add_callback { puts "Hello!" }
18
+
19
+ assert @test_object.test_event.callbacks.length == 1
20
+ end
21
+
22
+ def test_event_can_return_values
23
+ @test_object.test_event.add_callback { return 1 }
24
+
25
+ results = @test_object.test_event.fire
26
+ assert results == [1]
27
+ end
28
+
29
+ def test_single_subscriber_event_raises_error_on_second_callback
30
+ assert_nothing_raised do
31
+ @test_object.test_singleton_event.add_callback { puts "Hello!" }
32
+ end
33
+
34
+ assert_raises(Events::EventSubscriptionError) do
35
+ @test_object.test_singleton_event.add_callback { puts "Hello again!" }
36
+ end
37
+ end
38
+
39
+ def test_event_fire_alias
40
+ @test_object.on_test_event { puts "Hello" }
41
+ assert @test_object.test_event.callbacks.length == 1
42
+ end
43
+
44
+ def test_event_can_be_given_arguments
45
+ @test_object.on_test_event do |arg|
46
+ arg
47
+ end
48
+
49
+ results = @test_object.test_event.fire("abc")
50
+ assert results == ["abc"]
51
+ end
52
+ end
@@ -0,0 +1,30 @@
1
+ require "./lib/events"
2
+ require "test/unit"
3
+
4
+ # Test class in example
5
+ class EventsExample
6
+ include Events
7
+ event :activation
8
+
9
+ def activate
10
+ return_values = @activation.fire
11
+ return_values
12
+ end
13
+ end
14
+
15
+ # Test usage in example
16
+ class ExampleTests < Test::Unit::TestCase
17
+ def test_example_executes_correctly
18
+ example = EventsExample.new
19
+
20
+ example.on_activation do
21
+ "Hello"
22
+ end
23
+
24
+ example.on_activation do
25
+ "World!"
26
+ end
27
+
28
+ assert example.activate == ["Hello", "World!"]
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbevents
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonny Arnold
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-16 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.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
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.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubygems-tasks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
69
+ description: Provides an Event mixin for enabling classes to create events for public
70
+ and private subscription.
71
+ email: jonny.arnold89@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - README.md
79
+ - lib/events.rb
80
+ - rakefile
81
+ - rbevents.gemspec
82
+ - test/test_events.rb
83
+ - test/test_example.rb
84
+ homepage: https://github.com/jonnyarnold/rbevents
85
+ licenses:
86
+ - GPL
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.0.rc.2
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Events for Ruby
108
+ test_files:
109
+ - test/test_events.rb
110
+ - test/test_example.rb