rbevents 0.1.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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +1 -0
- data/README.md +40 -0
- data/lib/events.rb +119 -0
- data/rakefile +15 -0
- data/rbevents.gemspec +24 -0
- data/test/test_events.rb +52 -0
- data/test/test_example.rb +30 -0
- metadata +110 -0
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
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
|
data/test/test_events.rb
ADDED
|
@@ -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
|