callbacks_attachable 1.0.3 → 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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +42 -46
- data/callbacks_attachable.gemspec +9 -8
- data/lib/callbacks_attachable.rb +5 -64
- data/mrbgem.rake +16 -0
- data/{lib/callbacks_attachable → mrblib}/all_instances_callback.rb +3 -11
- data/{lib/callbacks_attachable/callback_handler.rb → mrblib/callback_registry.rb} +5 -5
- data/mrblib/callbacks_attachable.rb +59 -0
- data/{lib/callbacks_attachable → mrblib}/instance_callback.rb +3 -3
- data/{lib/callbacks_attachable → mrblib}/version.rb +1 -1
- metadata +16 -40
- data/Rakefile +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2585bc2a52a1a090b2d8792ce16a1b2b674769d9
|
4
|
+
data.tar.gz: b9212eaecc4af017f087bdbc17e0083c1678e048
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68601c07625b6fb386431b10bab77bae900a91d813aba44b50e7755a9c803e157cfd124d319d0dd133852a547ab3deaccd3e28bff38722a625c0d981329cf70c
|
7
|
+
data.tar.gz: 5caa67e516872ba4e4a46bacf92c77d954193517a4d5d062b59a05cbd2e230cc7e4603f1001a5e820470d8473b207c8b67dc56248dd15296850285add0890494
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# CallbacksAttachable
|
2
2
|
|
3
|
-
Attach callbacks to
|
4
|
-
|
5
|
-
|
3
|
+
Attach callbacks to a class and trigger them for all its instances or just one
|
4
|
+
particular instance. Additionally, instances can also have their own set of
|
5
|
+
individual callbacks.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -25,57 +25,54 @@ Or install it yourself as:
|
|
25
25
|
```ruby
|
26
26
|
require 'callbacks_attachable'
|
27
27
|
|
28
|
-
class
|
28
|
+
class AClass
|
29
29
|
include CallbacksAttachable
|
30
30
|
end
|
31
31
|
```
|
32
32
|
|
33
33
|
### Callbacks attached to the class
|
34
34
|
|
35
|
-
Attach callbacks to the class:
|
35
|
+
Attach callbacks for an event to the class with:
|
36
36
|
|
37
37
|
```ruby
|
38
|
-
callback =
|
38
|
+
callback = AClass.on(:event) do |method|
|
39
39
|
puts self.__send__(method)
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
-
Callbacks attached to
|
44
|
-
|
45
|
-
|
46
|
-
Trigger all `:event` callbacks with:
|
43
|
+
Callbacks attached to a class are executed in the context of each existing
|
44
|
+
instance. To trigger all `:event` callbacks for all instances of `AClass`, use:
|
47
45
|
|
48
46
|
```ruby
|
49
|
-
|
47
|
+
AClass.trigger(:event, :name) # => puts 'AClass'
|
50
48
|
```
|
51
49
|
|
52
|
-
The second and
|
53
|
-
callback.
|
50
|
+
The second and other arguments given to `.trigger` are passed to the callback.
|
54
51
|
|
55
|
-
Callbacks
|
56
|
-
|
52
|
+
Callbacks attached to a class can also be triggered for just one of its
|
53
|
+
instances with `.trigger_for`:
|
57
54
|
|
58
55
|
```ruby
|
59
|
-
|
60
|
-
|
61
|
-
# => puts the result of
|
56
|
+
an_instance = AClass.new
|
57
|
+
AClass.trigger_for(an_instance, :event, :__id__)
|
58
|
+
# => puts the result of an_instance.__id__
|
62
59
|
```
|
63
60
|
|
64
|
-
To detach a callback call `.off` with the event
|
65
|
-
|
61
|
+
To detach a callback call `.off` with the event's name and the callback handle
|
62
|
+
returned by `.on`:
|
66
63
|
|
67
64
|
```ruby
|
68
|
-
|
69
|
-
|
65
|
+
callback = AClass.on(:event) { do_something }
|
66
|
+
AClass.off(:event, callback)
|
70
67
|
```
|
71
68
|
|
72
69
|
If you want to execute a callback just a single time attach it with `.once_on`:
|
73
70
|
|
74
71
|
```ruby
|
75
|
-
|
76
|
-
|
72
|
+
AClass.once_on(:singularity) { puts 'callback called!' }
|
73
|
+
AClass.trigger(:singularity) # => puts 'callback called!' and immediately
|
77
74
|
# detaches the callback
|
78
|
-
|
75
|
+
AClass.trigger(:singularity) # => does nothing
|
79
76
|
```
|
80
77
|
|
81
78
|
To detach a callback when a condition is met use `.until_true_on`. The callback
|
@@ -83,43 +80,42 @@ will be detached if it has a truthy (!) return value.
|
|
83
80
|
|
84
81
|
```ruby
|
85
82
|
counter = 0
|
86
|
-
|
83
|
+
AClass.until_true_on(:count_to_two) do
|
87
84
|
puts counter
|
88
85
|
counter >= 2
|
89
86
|
end
|
90
87
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
88
|
+
AClass.trigger(:count_to_two) # => puts 0
|
89
|
+
AClass.trigger(:count_to_two) # => puts 1
|
90
|
+
AClass.trigger(:count_to_two) # => puts 2 and detaches the callback
|
91
|
+
AClass.trigger(:count_to_two) # => does nothing
|
95
92
|
```
|
96
93
|
|
97
94
|
### Callbacks attached to an instance
|
98
95
|
|
99
96
|
All above mentioned methods on the class level also exist for each instance of
|
100
|
-
the class. Callbacks
|
101
|
-
|
97
|
+
the class. Callbacks for an individual instance are executed by calling
|
98
|
+
`#trigger` on it. They are also called, when calling `.trigger` or
|
99
|
+
`.trigger_for(instance, ...)` on its class.
|
102
100
|
|
103
|
-
Callbacks are
|
104
|
-
the callback is the same object.
|
105
|
-
with the `context` option of the `#trigger` method as it is possible for
|
106
|
-
class callbacks.
|
101
|
+
Callbacks attached to individual instances are evaluated in their lexical scope.
|
102
|
+
So, `self` inside and outside the callback is the same object.
|
107
103
|
|
108
104
|
```ruby
|
109
|
-
|
110
|
-
|
105
|
+
an_instance1 = AClass.new
|
106
|
+
an_instance2 = AClass.new
|
111
107
|
|
112
|
-
callback1 =
|
113
|
-
callback2 =
|
108
|
+
callback1 = an_instance1.on(:event) { puts 'This is #1!' }
|
109
|
+
callback2 = an_instance2.on(:event) { puts 'This is #2!' }
|
114
110
|
|
115
|
-
|
116
|
-
|
111
|
+
an_instance1.trigger(:event) # => puts 'This is #1!'
|
112
|
+
an_instance2.trigger(:event) # => puts 'This is #2!'
|
117
113
|
|
118
|
-
|
114
|
+
AClass.trigger(:event) # => puts 'This is #1!' and 'This is #2!'
|
119
115
|
|
120
|
-
|
121
|
-
|
116
|
+
an_instance1.off(:event, callback)
|
117
|
+
an_instance2.off(:event, callback)
|
122
118
|
```
|
123
119
|
|
124
120
|
The two methods `#once_on` and `#until_true_on` are available for instances,
|
125
|
-
too
|
121
|
+
too. They work as you'd expect.
|
@@ -1,17 +1,20 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'callbacks_attachable/version'
|
2
|
+
require_relative 'mrblib/version'
|
5
3
|
|
6
4
|
Gem::Specification.new do |spec|
|
7
5
|
spec.name = "callbacks_attachable"
|
8
6
|
spec.version = CallbacksAttachable::VERSION
|
9
|
-
spec.
|
10
|
-
spec.
|
7
|
+
spec.summary = %q{Attach callbacks to classes or individual instances.}
|
8
|
+
spec.description = <<-DESC
|
9
|
+
Attach callbacks to a class and trigger them for all its instances or just one
|
10
|
+
particular instance. Additionally, instances can also have their own set of
|
11
|
+
individual callbacks.
|
12
|
+
DESC
|
11
13
|
|
12
|
-
spec.summary = %q{Attach callbacks to ruby objects. Then, trigger and detach them.}
|
13
14
|
spec.homepage = "https://github.com/christopheraue/ruby-callbacks_attachable"
|
14
15
|
spec.license = "MIT"
|
16
|
+
spec.authors = ["Christopher Aue"]
|
17
|
+
spec.email = "rubygems@christopheraue.net"
|
15
18
|
|
16
19
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -20,6 +23,4 @@ Gem::Specification.new do |spec|
|
|
20
23
|
spec.add_development_dependency "bundler", "~> 1.8"
|
21
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
22
25
|
spec.add_development_dependency "rspec", "~> 3.4"
|
23
|
-
spec.add_development_dependency "rspec-its"
|
24
|
-
spec.add_development_dependency "rspec-mocks-matchers-send_message", "~> 0.3"
|
25
26
|
end
|
data/lib/callbacks_attachable.rb
CHANGED
@@ -1,64 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
module CallbacksAttachable
|
7
|
-
def self.included(klass)
|
8
|
-
klass.extend ClassMethods
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def on(*args, &block)
|
13
|
-
__callback_handler__.on(*args, &block)
|
14
|
-
end
|
15
|
-
|
16
|
-
def once_on(*args, &block)
|
17
|
-
__callback_handler__.once_on(*args, &block)
|
18
|
-
end
|
19
|
-
|
20
|
-
def until_true_on(*args, &block)
|
21
|
-
__callback_handler__.until_true_on(*args, &block)
|
22
|
-
end
|
23
|
-
|
24
|
-
def off(*args)
|
25
|
-
__callback_handler__.off(*args)
|
26
|
-
end
|
27
|
-
|
28
|
-
def trigger(*args)
|
29
|
-
__callback_handler__.trigger(*args)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def __callback_handler__
|
35
|
-
@__callback_handler__ ||= CallbackHandler.new(self, AllInstancesCallback)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def on(*args, &block)
|
40
|
-
__callback_handler__.on(*args, &block)
|
41
|
-
end
|
42
|
-
|
43
|
-
def once_on(*args, &block)
|
44
|
-
__callback_handler__.once_on(*args, &block)
|
45
|
-
end
|
46
|
-
|
47
|
-
def until_true_on(*args, &block)
|
48
|
-
__callback_handler__.until_true_on(*args, &block)
|
49
|
-
end
|
50
|
-
|
51
|
-
def off(*args)
|
52
|
-
__callback_handler__.off(*args)
|
53
|
-
end
|
54
|
-
|
55
|
-
def trigger(*args)
|
56
|
-
self.class.trigger(*args, instance: self) and __callback_handler__.trigger(*args)
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def __callback_handler__
|
62
|
-
@__callback_handler__ ||= CallbackHandler.new(self, InstanceCallback)
|
63
|
-
end
|
64
|
-
end
|
1
|
+
require_relative "../mrblib/callbacks_attachable"
|
2
|
+
require_relative "../mrblib/version"
|
3
|
+
require_relative "../mrblib/callback_registry"
|
4
|
+
require_relative "../mrblib/instance_callback"
|
5
|
+
require_relative "../mrblib/all_instances_callback"
|
data/mrbgem.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'mrblib/version'
|
2
|
+
|
3
|
+
MRuby::Gem::Specification.new('mruby-callbacks_attachable') do |spec|
|
4
|
+
spec.version = CallbacksAttachable::VERSION
|
5
|
+
spec.summary = %q{Attach callbacks to classes or individual instances.}
|
6
|
+
spec.description = <<-DESC
|
7
|
+
Attach callbacks to a class and trigger them for all its instances or just one
|
8
|
+
particular instance. Additionally, instances can also have their own set of
|
9
|
+
individual callbacks.
|
10
|
+
DESC
|
11
|
+
spec.homepage = "https://github.com/christopheraue/ruby-callbacks_attachable"
|
12
|
+
spec.license = 'MIT'
|
13
|
+
spec.authors = ['Christopher Aue']
|
14
|
+
|
15
|
+
spec.add_dependency 'mruby-objectspace', :core => 'mruby-objectspace'
|
16
|
+
end
|
@@ -1,21 +1,13 @@
|
|
1
1
|
module CallbacksAttachable
|
2
2
|
class AllInstancesCallback
|
3
|
-
def initialize(klass,
|
3
|
+
def initialize(klass, opts = {}, &callback)
|
4
4
|
@class = klass
|
5
|
-
@skip = skip
|
5
|
+
@skip = opts.fetch(:skip, 0)
|
6
6
|
@callback = callback
|
7
7
|
@call_counts = {}
|
8
8
|
end
|
9
9
|
|
10
|
-
def call(
|
11
|
-
if instance = opts[:instance]
|
12
|
-
call_for_instance(instance, *args)
|
13
|
-
else
|
14
|
-
ObjectSpace.each_object(@class).all?{ |inst| call_for_instance(inst, *args) }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def call_for_instance(instance, *args)
|
10
|
+
def call(instance, args)
|
19
11
|
@call_counts[instance.__id__] = @call_counts[instance.__id__].to_i + 1
|
20
12
|
return true if @call_counts[instance.__id__] <= @skip
|
21
13
|
false != instance.instance_exec(*args, &@callback)
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module CallbacksAttachable
|
2
|
-
class
|
2
|
+
class CallbackRegistry
|
3
3
|
def initialize(object, callback_class)
|
4
4
|
@object = object
|
5
5
|
@callback_class = callback_class
|
6
6
|
end
|
7
7
|
|
8
|
-
def on(event,
|
8
|
+
def on(event, opts = {}, &callback)
|
9
9
|
__callbacks__[event] ||= []
|
10
|
-
__callbacks__[event] << @callback_class.new(@object,
|
10
|
+
__callbacks__[event] << @callback_class.new(@object, opts, &callback)
|
11
11
|
__callbacks__[event].last
|
12
12
|
end
|
13
13
|
|
@@ -28,12 +28,12 @@ module CallbacksAttachable
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def trigger(event,
|
31
|
+
def trigger(instance, event, args)
|
32
32
|
return true if __callbacks__[event].nil?
|
33
33
|
|
34
34
|
# dup the callback list so that removing callbacks while iterating does
|
35
35
|
# still call all callbacks during map.
|
36
|
-
__callbacks__[event].dup.all?{ |callback| callback.call(
|
36
|
+
__callbacks__[event].dup.all?{ |callback| callback.call(instance, args) }
|
37
37
|
end
|
38
38
|
|
39
39
|
def off(event, callback)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module CallbacksAttachable
|
2
|
+
def self.included(klass)
|
3
|
+
klass.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def on(*args, &block)
|
8
|
+
__callback_registry__.on(*args, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def once_on(*args, &block)
|
12
|
+
__callback_registry__.once_on(*args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def until_true_on(*args, &block)
|
16
|
+
__callback_registry__.until_true_on(*args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def off(*args)
|
20
|
+
__callback_registry__.off(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def trigger(event, *args)
|
24
|
+
ObjectSpace.each_object(self).all?{ |inst| inst.trigger(event, *args) }
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def __callback_registry__
|
30
|
+
@__callback_registry__ ||= CallbackRegistry.new(self, AllInstancesCallback)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def on(*args, &block)
|
35
|
+
__callback_registry__.on(*args, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def once_on(*args, &block)
|
39
|
+
__callback_registry__.once_on(*args, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def until_true_on(*args, &block)
|
43
|
+
__callback_registry__.until_true_on(*args, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def off(*args)
|
47
|
+
__callback_registry__.off(*args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def trigger(event, *args)
|
51
|
+
self.class.__send__(:__callback_registry__).trigger(self, event, args) and __callback_registry__.trigger(self, event, args)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def __callback_registry__
|
57
|
+
@__callback_registry__ ||= CallbackRegistry.new(self, InstanceCallback)
|
58
|
+
end
|
59
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module CallbacksAttachable
|
2
2
|
class InstanceCallback
|
3
|
-
def initialize(instance,
|
3
|
+
def initialize(instance, opts = {}, &callback)
|
4
4
|
@instance = instance
|
5
|
-
@skip = skip
|
5
|
+
@skip = opts.fetch(:skip, 0)
|
6
6
|
@callback = callback
|
7
7
|
@call_count = 0
|
8
8
|
end
|
9
9
|
|
10
|
-
def call(
|
10
|
+
def call(instance, args)
|
11
11
|
@call_count += 1
|
12
12
|
return true if @call_count <= @skip
|
13
13
|
@callback.call(*args) != false
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: callbacks_attachable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Aue
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,37 +52,11 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.4'
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rspec-mocks-matchers-send_message
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0.3'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0.3'
|
83
|
-
description:
|
84
|
-
email:
|
85
|
-
- mail@christopheraue.net
|
55
|
+
description: |
|
56
|
+
Attach callbacks to a class and trigger them for all its instances or just one
|
57
|
+
particular instance. Additionally, instances can also have their own set of
|
58
|
+
individual callbacks.
|
59
|
+
email: rubygems@christopheraue.net
|
86
60
|
executables: []
|
87
61
|
extensions: []
|
88
62
|
extra_rdoc_files: []
|
@@ -92,13 +66,14 @@ files:
|
|
92
66
|
- Gemfile
|
93
67
|
- LICENSE.txt
|
94
68
|
- README.md
|
95
|
-
- Rakefile
|
96
69
|
- callbacks_attachable.gemspec
|
97
70
|
- lib/callbacks_attachable.rb
|
98
|
-
-
|
99
|
-
-
|
100
|
-
-
|
101
|
-
-
|
71
|
+
- mrbgem.rake
|
72
|
+
- mrblib/all_instances_callback.rb
|
73
|
+
- mrblib/callback_registry.rb
|
74
|
+
- mrblib/callbacks_attachable.rb
|
75
|
+
- mrblib/instance_callback.rb
|
76
|
+
- mrblib/version.rb
|
102
77
|
homepage: https://github.com/christopheraue/ruby-callbacks_attachable
|
103
78
|
licenses:
|
104
79
|
- MIT
|
@@ -119,8 +94,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
94
|
version: '0'
|
120
95
|
requirements: []
|
121
96
|
rubyforge_project:
|
122
|
-
rubygems_version: 2.
|
97
|
+
rubygems_version: 2.5.1
|
123
98
|
signing_key:
|
124
99
|
specification_version: 4
|
125
|
-
summary: Attach callbacks to
|
100
|
+
summary: Attach callbacks to classes or individual instances.
|
126
101
|
test_files: []
|
102
|
+
has_rdoc:
|
data/Rakefile
DELETED