ruby_events 1.1.0.beta2 → 1.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.
- data/README.markdown +29 -0
- data/Rakefile +0 -23
- data/lib/ruby_events.rb +2 -112
- data/lib/ruby_events/core.rb +106 -0
- data/lib/ruby_events/object_patch.rb +10 -0
- metadata +27 -16
data/README.markdown
CHANGED
@@ -60,6 +60,11 @@ a little bit of sugar:
|
|
60
60
|
|
61
61
|
a << 'this is a test'
|
62
62
|
|
63
|
+
You can supply multiple methods to fire a single event type on, useful for
|
64
|
+
catching methods and their aliases:
|
65
|
+
|
66
|
+
a.events.fire_on_method(['<<'.to_sym, :push], :item_injected)
|
67
|
+
|
63
68
|
You can supply the `listen` method with a Proc, an array of Procs, or a block.
|
64
69
|
You can also give it a mixute of Procs and a block if you really want:
|
65
70
|
|
@@ -88,3 +93,27 @@ Effectively, you can use the events as callbacks on any method:
|
|
88
93
|
puts a.merge(b)
|
89
94
|
|
90
95
|
All ruby_events functionality is just an object.events call away.
|
96
|
+
|
97
|
+
## Licence
|
98
|
+
|
99
|
+
The MIT License
|
100
|
+
|
101
|
+
Copyright (c) 2011 Nathan Kleyn
|
102
|
+
|
103
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
104
|
+
of this software and associated documentation files (the "Software"), to deal
|
105
|
+
in the Software without restriction, including without limitation the rights
|
106
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
107
|
+
copies of the Software, and to permit persons to whom the Software is
|
108
|
+
furnished to do so, subject to the following conditions:
|
109
|
+
|
110
|
+
The above copyright notice and this permission notice shall be included in
|
111
|
+
all copies or substantial portions of the Software.
|
112
|
+
|
113
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
114
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
115
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
116
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
117
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
118
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
119
|
+
THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,32 +1,9 @@
|
|
1
|
-
require 'lib/ruby_events'
|
2
1
|
require 'rubygems'
|
3
2
|
require 'rake'
|
4
3
|
require 'rake/clean'
|
5
|
-
require 'rubygems/package_task'
|
6
4
|
require 'rdoc/task'
|
7
5
|
require 'rake/testtask'
|
8
6
|
|
9
|
-
spec = Gem::Specification.new do |s|
|
10
|
-
s.name = 'ruby_events'
|
11
|
-
s.version = RubyEvents::Events.version
|
12
|
-
s.extra_rdoc_files = ['README.markdown']
|
13
|
-
s.summary = 'A really simple event implementation that hooks into the Object class. Now all your objects can join in the fun of firing events!'
|
14
|
-
s.description = s.summary + ' See http://github.com/nathankleyn/ruby_events for more information.'
|
15
|
-
s.author = 'Nathan Kleyn'
|
16
|
-
s.email = 'nathan@unfinitydesign.com'
|
17
|
-
s.homepage = 'http://github.com/nathankleyn/ruby_events'
|
18
|
-
# s.executables = ['your_executable_here']
|
19
|
-
s.files = %w(README.markdown Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
20
|
-
s.require_path = "lib"
|
21
|
-
s.bindir = "bin"
|
22
|
-
end
|
23
|
-
|
24
|
-
Gem::PackageTask.new(spec) do |p|
|
25
|
-
p.gem_spec = spec
|
26
|
-
p.need_tar = true
|
27
|
-
p.need_zip = true
|
28
|
-
end
|
29
|
-
|
30
7
|
RDoc::Task.new do |rdoc|
|
31
8
|
files =['README.markdown', 'lib/**/*.rb']
|
32
9
|
rdoc.rdoc_files.add(files)
|
data/lib/ruby_events.rb
CHANGED
@@ -1,112 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# an instance of the RubyEvents::Events class. By calling the methods on this
|
4
|
-
# accessor, you can set up and listen to events or callbacks as fired by this
|
5
|
-
# class.
|
6
|
-
module RubyEvents
|
7
|
-
# The Events class. Contains all the methods and functionality that drives
|
8
|
-
# the actual processes of adding, listening, calling and receiving events.
|
9
|
-
class Events
|
10
|
-
# The current version of RubyEvents.
|
11
|
-
def self.version
|
12
|
-
'1.1.0.beta2'
|
13
|
-
end
|
14
|
-
|
15
|
-
# Initialize the events class by instantiating the class methods we'll be
|
16
|
-
# using.
|
17
|
-
def initialize(parent)
|
18
|
-
@parent, @events = parent, {}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Add a listener to the passed event type. You can pass a Proc, an array of
|
22
|
-
# Proc's, or a block.
|
23
|
-
def listen(event_type, procs = nil, &block)
|
24
|
-
@events[event_type] = [] unless event_is_defined(event_type)
|
25
|
-
procs_collected = []
|
26
|
-
if procs.respond_to?(:each) && procs.respond_to?(:to_a)
|
27
|
-
procs_collected += procs.to_a
|
28
|
-
elsif procs
|
29
|
-
procs_collected << procs
|
30
|
-
end
|
31
|
-
procs_collected << block if block
|
32
|
-
@events[event_type] += procs_collected
|
33
|
-
end
|
34
|
-
|
35
|
-
# Fire all registered listeners to the passed event, passing them the
|
36
|
-
# arguments as provided.
|
37
|
-
def fire(event_type, *arguments)
|
38
|
-
@events[event_type].each do |event|
|
39
|
-
event.call(*arguments)
|
40
|
-
end if event_is_defined(event_type)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Set an event to fire when passed method is called. This is useful for
|
44
|
-
# adding callbacks or events to built-in methods.
|
45
|
-
def fire_on_method(method, event_type, &block)
|
46
|
-
# We alias @parent to parent here, because class_eval can't see outside
|
47
|
-
# this scope otherwise.
|
48
|
-
parent, old_method = @parent, ('ruby_events_' + method.to_s + '_event_old').to_sym
|
49
|
-
if parent && parent.respond_to?(method)
|
50
|
-
parent.class.class_eval do
|
51
|
-
# If the parent is already responding to the alias method, it means
|
52
|
-
# the fire_on_method event was already triggered. Remove the other
|
53
|
-
# event and continue if this happens.
|
54
|
-
if parent.respond_to?(old_method, true)
|
55
|
-
remove_method method
|
56
|
-
alias_method method, old_method
|
57
|
-
remove_method old_method
|
58
|
-
end
|
59
|
-
|
60
|
-
alias_method old_method, method
|
61
|
-
private old_method
|
62
|
-
|
63
|
-
# Make sure the self.send is at the end, or we won't return what we
|
64
|
-
# are supposed to.
|
65
|
-
define_method method do |*args|
|
66
|
-
events.fire(event_type, *args)
|
67
|
-
block.call(*args) if block # Calling the block we've been passed
|
68
|
-
__send__(old_method, *args)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
else
|
72
|
-
raise 'The given object does not respond to method you are trying to intercept calls to.'
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Remove a method from the listening queue.
|
77
|
-
def remove(event_type, event)
|
78
|
-
@events[event_type].delete_if {|stored_event| stored_event == event} if event_is_defined(event_type)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Remove a fire on method alias event.
|
82
|
-
def remove_fire_on_method(method)
|
83
|
-
parent, old_method = @parent, ('ruby_events_' + method.to_s + '_event_old').to_sym
|
84
|
-
parent.class.class_eval do
|
85
|
-
if parent.respond_to?(old_method, true)
|
86
|
-
remove_method method
|
87
|
-
alias_method method, old_method
|
88
|
-
public method
|
89
|
-
else
|
90
|
-
raise 'The fire on method trigger you were trying to remove does not exist.'
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
# Checks if an event of event_type is defined in the collection of events.
|
97
|
-
def event_is_defined(event_type)
|
98
|
-
@events.has_key?(event_type)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Extending the Object class with the events accessor.
|
104
|
-
class Object
|
105
|
-
attr_writer :events
|
106
|
-
|
107
|
-
# Attribute reader for the events accessor. Returns a new instance of the
|
108
|
-
# events class if not defined, or the already defined class otherwise.
|
109
|
-
def events
|
110
|
-
@events ||= RubyEvents::Events.new(self)
|
111
|
-
end
|
112
|
-
end
|
1
|
+
require File.join(File.dirname(__FILE__), "ruby_events/core")
|
2
|
+
require File.join(File.dirname(__FILE__), "ruby_events/object_patch")
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# The RubyEvents module contains the core logic used by the events firing class.
|
2
|
+
# All Object's are extended by default with an events accessor that is set to
|
3
|
+
# an instance of the RubyEvents::Events class. By calling the methods on this
|
4
|
+
# accessor, you can set up and listen to events or callbacks as fired by this
|
5
|
+
# class.
|
6
|
+
module RubyEvents
|
7
|
+
# The Events class. Contains all the methods and functionality that drives
|
8
|
+
# the actual processes of adding, listening, calling and receiving events.
|
9
|
+
class Events
|
10
|
+
# The current version of RubyEvents.
|
11
|
+
def self.version
|
12
|
+
'1.1.0'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Initialize the events class by instantiating the class methods we'll be
|
16
|
+
# using.
|
17
|
+
def initialize(parent)
|
18
|
+
@parent, @events = parent, {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Add a listener to the passed event type. You can pass a Proc, an array of
|
22
|
+
# Proc's, or a block.
|
23
|
+
def listen(event_type, procs = nil, &block)
|
24
|
+
@events[event_type] = [] unless event_is_defined(event_type)
|
25
|
+
procs_collected = []
|
26
|
+
if procs.respond_to?(:each) && procs.respond_to?(:to_a)
|
27
|
+
procs_collected += procs.to_a
|
28
|
+
elsif procs
|
29
|
+
procs_collected << procs
|
30
|
+
end
|
31
|
+
procs_collected << block if block
|
32
|
+
@events[event_type] += procs_collected
|
33
|
+
end
|
34
|
+
|
35
|
+
# Fire all registered listeners to the passed event, passing them the
|
36
|
+
# arguments as provided.
|
37
|
+
def fire(event_type, *arguments)
|
38
|
+
@events[event_type].each do |event|
|
39
|
+
event.call(*arguments)
|
40
|
+
end if event_is_defined(event_type)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set an event to fire when passed method is called. This is useful for
|
44
|
+
# adding callbacks or events to built-in methods.
|
45
|
+
def fire_on_method(method, event_type, &block)
|
46
|
+
if method.is_a? Array
|
47
|
+
method.map { |sym| fire_on_method(sym, event_type, &block) }
|
48
|
+
return
|
49
|
+
end
|
50
|
+
|
51
|
+
# We alias @parent to parent here, because class_eval can't see outside
|
52
|
+
# this scope otherwise.
|
53
|
+
parent, old_method = @parent, ('ruby_events_' + method.to_s + '_event_old').to_sym
|
54
|
+
if parent && parent.respond_to?(method)
|
55
|
+
parent.class.class_eval do
|
56
|
+
# If the parent is already responding to the alias method, it means
|
57
|
+
# the fire_on_method event was already triggered. Remove the other
|
58
|
+
# event and continue if this happens.
|
59
|
+
if parent.respond_to?(old_method, true)
|
60
|
+
remove_method method
|
61
|
+
alias_method method, old_method
|
62
|
+
remove_method old_method
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method old_method, method
|
66
|
+
private old_method
|
67
|
+
|
68
|
+
# Make sure the self.send is at the end, or we won't return what we
|
69
|
+
# are supposed to.
|
70
|
+
define_method method do |*args|
|
71
|
+
events.fire(event_type, *args)
|
72
|
+
block.call(*args) if block # Calling the block we've been passed
|
73
|
+
__send__(old_method, *args)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
raise 'The given object does not respond to method you are trying to intercept calls to.'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Remove a method from the listening queue.
|
82
|
+
def remove(event_type, event)
|
83
|
+
@events[event_type].delete_if {|stored_event| stored_event == event} if event_is_defined(event_type)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Remove a fire on method alias event.
|
87
|
+
def remove_fire_on_method(method)
|
88
|
+
parent, old_method = @parent, ('ruby_events_' + method.to_s + '_event_old').to_sym
|
89
|
+
parent.class.class_eval do
|
90
|
+
if parent.respond_to?(old_method, true)
|
91
|
+
remove_method method
|
92
|
+
alias_method method, old_method
|
93
|
+
public method
|
94
|
+
else
|
95
|
+
raise 'The fire on method trigger you were trying to remove does not exist.'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
# Checks if an event of event_type is defined in the collection of events.
|
102
|
+
def event_is_defined(event_type)
|
103
|
+
@events.has_key?(event_type)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Extending the Object class with the events accessor.
|
2
|
+
class Object
|
3
|
+
attr_writer :events
|
4
|
+
|
5
|
+
# Attribute reader for the events accessor. Returns a new instance of the
|
6
|
+
# events class if not defined, or the already defined class otherwise.
|
7
|
+
def events
|
8
|
+
@events ||= RubyEvents::Events.new(self)
|
9
|
+
end
|
10
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_events
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
9
|
- 0
|
10
|
-
|
11
|
-
- 2
|
12
|
-
version: 1.1.0.beta2
|
10
|
+
version: 1.1.0
|
13
11
|
platform: ruby
|
14
12
|
authors:
|
15
13
|
- Nathan Kleyn
|
@@ -17,10 +15,23 @@ autorequire:
|
|
17
15
|
bindir: bin
|
18
16
|
cert_chain: []
|
19
17
|
|
20
|
-
date: 2011-
|
21
|
-
dependencies:
|
22
|
-
|
23
|
-
|
18
|
+
date: 2011-06-17 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
description: A really simple event implementation that hooks into the Object classpec. Now all your objects can join in the fun of firing events! See http://github.com/nathankleyn/ruby_events for more information.
|
24
35
|
email: nathan@unfinitydesign.com
|
25
36
|
executables: []
|
26
37
|
|
@@ -32,6 +43,8 @@ files:
|
|
32
43
|
- README.markdown
|
33
44
|
- Rakefile
|
34
45
|
- lib/ruby_events.rb
|
46
|
+
- lib/ruby_events/object_patch.rb
|
47
|
+
- lib/ruby_events/core.rb
|
35
48
|
homepage: http://github.com/nathankleyn/ruby_events
|
36
49
|
licenses: []
|
37
50
|
|
@@ -52,20 +65,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
66
|
none: false
|
54
67
|
requirements:
|
55
|
-
- - "
|
68
|
+
- - ">="
|
56
69
|
- !ruby/object:Gem::Version
|
57
|
-
hash:
|
70
|
+
hash: 3
|
58
71
|
segments:
|
59
|
-
-
|
60
|
-
|
61
|
-
- 1
|
62
|
-
version: 1.3.1
|
72
|
+
- 0
|
73
|
+
version: "0"
|
63
74
|
requirements: []
|
64
75
|
|
65
76
|
rubyforge_project:
|
66
77
|
rubygems_version: 1.7.2
|
67
78
|
signing_key:
|
68
79
|
specification_version: 3
|
69
|
-
summary: A really simple event implementation that hooks into the Object
|
80
|
+
summary: A really simple event implementation that hooks into the Object classpec. Now all your objects can join in the fun of firing events!
|
70
81
|
test_files: []
|
71
82
|
|