disposable 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGES.md +9 -0
- data/README.md +4 -0
- data/lib/disposable/callback.rb +26 -24
- data/lib/disposable/version.rb +1 -1
- data/test/callback_group_test.rb +38 -26
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31d57820d95d0f0c679a690f4f5571fecbe972d4
|
4
|
+
data.tar.gz: 9ca35177d6953ebdc3fc2d3b8d7f2040177586ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56f4d3c54f0c4515da447474ab3618cd218eafe534377a0e7d0be4b4ac34e1d9d611c94874b44167fb176aea725b6f1dcabe5f1c26df4e05fde5e877cf4d5467
|
7
|
+
data.tar.gz: 38dce808bde55025f706c3900290569410a7fce94ce13882489fa4dabf93f36c4d4c10930f7ddddb847238c43bcbac12c522c46c04594f9909a3c93618a9e3a3
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 0.2.1
|
2
|
+
|
3
|
+
* In `Callback::Group#call`, the `context` option now allows running callbacks in different contexts. Per default, the group instance is context.
|
4
|
+
* Callback handler methods now receive two options: the twin and the options hash passed into `Group#call`. This allows injecting arbitrary objects into callbacks, which is pretty awesome!
|
5
|
+
|
1
6
|
# 0.2.0
|
2
7
|
|
3
8
|
* Internally, use [Declarative](https://github.com/apotonick/declarative) now for schema creation, resulting in the following internal changes.
|
@@ -7,6 +12,10 @@
|
|
7
12
|
* Added `:exclude_properties` to `Rescheme`.
|
8
13
|
* Runs with Representable 2.4 and 3.0.
|
9
14
|
|
15
|
+
# 0.1.15
|
16
|
+
|
17
|
+
* Restrict to Representable < 2.4.
|
18
|
+
|
10
19
|
# 0.1.14
|
11
20
|
|
12
21
|
* Allow to nil-out nested twins.
|
data/README.md
CHANGED
@@ -462,6 +462,8 @@ class AlbumTwin < Disposable::Twin
|
|
462
462
|
|
463
463
|
## Imperative Callbacks
|
464
464
|
|
465
|
+
Please refer to the [full documentation](http://trailblazer.to/gems/disposable/callback.html).
|
466
|
+
|
465
467
|
Note: [Chapter 8 of the Trailblazer](http://leanpub.com/trailblazer) book is dedicated to callbacks and discusses them in great detail.
|
466
468
|
|
467
469
|
Callbacks use the fact that twins track state changes. This allows to execute callbacks on certain conditions.
|
@@ -529,6 +531,8 @@ AfterSave.new(twin).(context: self)
|
|
529
531
|
|
530
532
|
Methods like `:sing!` will be invoked on the `:context` object. Likewise, nested properties will be retrieved by simply calling the getter on the twin, like `twin.songs`.
|
531
533
|
|
534
|
+
An options hash is passed as the second argument. # TODO: document Group.(operation: Object.new).
|
535
|
+
|
532
536
|
Again, only the events that match will be invoked. If the top level twin hasn't changed, `expire_cache!` won't be invoked. This works by simply using `Callback` under the hood.
|
533
537
|
|
534
538
|
## Callback Inheritance
|
data/lib/disposable/callback.rb
CHANGED
@@ -39,7 +39,7 @@ module Disposable::Callback
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.remove!(event, callback)
|
42
|
-
hooks.delete hooks.find { |cfg| cfg[0] == event && cfg[1]
|
42
|
+
hooks.delete hooks.find { |cfg| cfg[0] == event && cfg[1] == callback }
|
43
43
|
end
|
44
44
|
|
45
45
|
|
@@ -57,19 +57,19 @@ module Disposable::Callback
|
|
57
57
|
|
58
58
|
class << self
|
59
59
|
%w(on_add on_delete on_destroy on_update on_create on_change).each do |event|
|
60
|
-
define_method event do
|
61
|
-
heritage.record(event,
|
60
|
+
define_method event do |method, options={}|
|
61
|
+
heritage.record(event, method, options)
|
62
62
|
|
63
|
-
hooks << [event.to_sym,
|
63
|
+
hooks << [event.to_sym, method, options] # DISCUSS: can't we simply instantiate Callables here?
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
|
69
69
|
def call(options={})
|
70
|
-
self.class.hooks.each do |event,
|
70
|
+
self.class.hooks.each do |event, method, property_options|
|
71
71
|
if event == "property" # FIXME: make nicer.
|
72
|
-
definition = self.class.definitions.get(
|
72
|
+
definition = self.class.definitions.get(method)
|
73
73
|
twin = @twin.send(definition[:name]) # album.songs
|
74
74
|
|
75
75
|
# recursively call nested group.
|
@@ -77,22 +77,24 @@ module Disposable::Callback
|
|
77
77
|
next
|
78
78
|
end
|
79
79
|
|
80
|
-
invocations << callback!(event, options,
|
80
|
+
invocations << callback!(event, options, method, property_options)
|
81
81
|
end
|
82
82
|
|
83
83
|
self
|
84
84
|
end
|
85
85
|
|
86
86
|
private
|
87
|
-
# Runs one callback.
|
88
|
-
def callback!(event, options, args
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
# Runs one callback, e.g. for `on_change :smile!`.
|
88
|
+
def callback!(event, options, method, property_options) # TODO: remove args.
|
89
|
+
context = options[:context] || self # TODO: test me.
|
90
|
+
|
91
|
+
# TODO: Use Option::Value here. this could be created straight in the DSL with the twin being passed in.
|
92
|
+
if context.methods.include?(method) && context.method(method).arity == 1 # TODO: remove in 0.3.
|
93
|
+
warn "[Disposable] Callback handlers now receive two options: #{method}(twin, options)."
|
94
|
+
return Dispatch.new(@twin).(event, method, property_options) { |twin| context.send(method, twin) }
|
95
|
+
end
|
93
96
|
|
94
|
-
|
95
|
-
Dispatch.new(@twin).(event, method, *options) { |twin| context.send(method, twin) }
|
97
|
+
Dispatch.new(@twin).(event, method, property_options) { |twin| context.send(method, twin, options) }
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
@@ -105,33 +107,33 @@ module Disposable::Callback
|
|
105
107
|
@invocations = []
|
106
108
|
end
|
107
109
|
|
108
|
-
def call(event, method,
|
109
|
-
send(event,
|
110
|
+
def call(event, method, property_options, &block) # FIXME: as long as we only support method, pass in here.
|
111
|
+
send(event, property_options, &block)
|
110
112
|
[event, method, @invocations]
|
111
113
|
end
|
112
114
|
|
113
115
|
def on_add(state=nil, &block) # how to call it once, for "all"?
|
114
116
|
# @twins can only be Collection instance.
|
115
117
|
@twins.added.each do |item|
|
116
|
-
run!(item, &block) if state.
|
118
|
+
run!(item, &block) if ! state.is_a?(Symbol)
|
117
119
|
run!(item, &block) if item.created? && state == :created # :created # DISCUSS: should we really keep that?
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
121
|
-
def on_delete(&block)
|
123
|
+
def on_delete(*, &block)
|
122
124
|
# @twins can only be Collection instance.
|
123
125
|
@twins.deleted.each do |item|
|
124
126
|
run!(item, &block)
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
128
|
-
def on_destroy(&block)
|
130
|
+
def on_destroy(*, &block)
|
129
131
|
@twins.destroyed.each do |item|
|
130
132
|
run!(item, &block)
|
131
133
|
end
|
132
134
|
end
|
133
135
|
|
134
|
-
def on_update(&block)
|
136
|
+
def on_update(*, &block)
|
135
137
|
@twins.each do |twin|
|
136
138
|
next if twin.created?
|
137
139
|
next unless twin.persisted? # only persisted can be updated.
|
@@ -140,15 +142,15 @@ module Disposable::Callback
|
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
|
-
def on_create(&block)
|
145
|
+
def on_create(*, &block)
|
144
146
|
@twins.each do |twin|
|
145
147
|
next unless twin.created?
|
146
148
|
run!(twin, &block)
|
147
149
|
end
|
148
150
|
end
|
149
151
|
|
150
|
-
def on_change(
|
151
|
-
name =
|
152
|
+
def on_change(property_options={}, &block)
|
153
|
+
name = property_options[:property]
|
152
154
|
|
153
155
|
@twins.each do |twin|
|
154
156
|
if name
|
data/lib/disposable/version.rb
CHANGED
data/test/callback_group_test.rb
CHANGED
@@ -14,12 +14,12 @@ class CallbackGroupTest < MiniTest::Spec
|
|
14
14
|
|
15
15
|
# on_delete :notify_deleted_author! # in Update!
|
16
16
|
|
17
|
-
def notify_album!(twin)
|
18
|
-
|
17
|
+
def notify_album!(twin, options)
|
18
|
+
options[:content] << "notify_album!"
|
19
19
|
end
|
20
20
|
|
21
|
-
def reset_song!(twin)
|
22
|
-
|
21
|
+
def reset_song!(twin, options)
|
22
|
+
options[:content] << "reset_song!"
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -29,7 +29,7 @@ class CallbackGroupTest < MiniTest::Spec
|
|
29
29
|
on_create :expire_cache! # on_change
|
30
30
|
on_update :expire_cache!
|
31
31
|
|
32
|
-
def change!(twin)
|
32
|
+
def change!(twin, options)
|
33
33
|
@output = "Album has changed!"
|
34
34
|
end
|
35
35
|
end
|
@@ -66,6 +66,8 @@ class CallbackGroupTest < MiniTest::Spec
|
|
66
66
|
]
|
67
67
|
end
|
68
68
|
|
69
|
+
# trigger songs:on_add, and on_change.
|
70
|
+
let (:content) { "" }
|
69
71
|
it do
|
70
72
|
twin = AlbumTwin.new(Album.new)
|
71
73
|
twin.songs << Song.new(title: "Dead To Me")
|
@@ -73,10 +75,7 @@ class CallbackGroupTest < MiniTest::Spec
|
|
73
75
|
|
74
76
|
twin.name = "Dear Landlord"
|
75
77
|
|
76
|
-
group = Group.new(twin).()
|
77
|
-
# Disposable::Callback::Dispatch.new(twin).on_change{ |twin| puts twin;puts }
|
78
|
-
|
79
|
-
# pp group.invocations
|
78
|
+
group = Group.new(twin).(content: content)
|
80
79
|
|
81
80
|
group.invocations.must_equal [
|
82
81
|
[:on_change, :change!, [twin]],
|
@@ -87,23 +86,36 @@ class CallbackGroupTest < MiniTest::Spec
|
|
87
86
|
[:on_update, :expire_cache!, []],
|
88
87
|
]
|
89
88
|
|
89
|
+
content.must_equal "notify_album!notify_album!reset_song!reset_song!"
|
90
90
|
group.output.must_equal "Album has changed!"
|
91
91
|
end
|
92
92
|
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
93
97
|
# context.
|
94
98
|
class Operation
|
95
99
|
attr_reader :output
|
96
100
|
|
97
|
-
def change!(twin)
|
98
|
-
|
101
|
+
def change!(twin, options)
|
102
|
+
options[:content] << "Op: changed! [#{options[:context].class}]"
|
103
|
+
end
|
104
|
+
|
105
|
+
def notify_album!(twin, options)
|
106
|
+
options[:content] << "Op: notify_album! [#{options[:context].class}]"
|
107
|
+
end
|
108
|
+
|
109
|
+
def reset_song!(twin, options)
|
110
|
+
options[:content] << "Op: reset_song! [#{options[:context].class}]"
|
99
111
|
end
|
100
112
|
|
101
|
-
def
|
102
|
-
|
113
|
+
def rehash_name!(twin, options)
|
114
|
+
options[:content] << "Op: rehash_name! [#{options[:context].class}]"
|
103
115
|
end
|
104
116
|
|
105
|
-
def
|
106
|
-
|
117
|
+
def expire_cache!(twin, options)
|
118
|
+
options[:content] << "Op: expire_cache! [#{options[:context].class}]"
|
107
119
|
end
|
108
120
|
end
|
109
121
|
|
@@ -113,7 +125,7 @@ class CallbackGroupTest < MiniTest::Spec
|
|
113
125
|
|
114
126
|
twin.name = "Dear Landlord"
|
115
127
|
|
116
|
-
group = Group.new(twin).(context: context = Operation.new)
|
128
|
+
group = Group.new(twin).(context: context = Operation.new, content: content)
|
117
129
|
# Disposable::Callback::Dispatch.new(twin).on_change{ |twin| puts twin;puts }
|
118
130
|
|
119
131
|
# pp group.invocations
|
@@ -127,7 +139,7 @@ class CallbackGroupTest < MiniTest::Spec
|
|
127
139
|
[:on_update, :expire_cache!, []],
|
128
140
|
]
|
129
141
|
|
130
|
-
|
142
|
+
content.must_equal "Op: changed! [CallbackGroupTest::Operation]Op: notify_album! [CallbackGroupTest::Operation]Op: reset_song! [CallbackGroupTest::Operation]"
|
131
143
|
end
|
132
144
|
end
|
133
145
|
|
@@ -147,11 +159,11 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
|
|
147
159
|
|
148
160
|
it do
|
149
161
|
Group.hooks.size.must_equal 4
|
150
|
-
Group.hooks[0].to_s.must_equal "[:on_change,
|
162
|
+
Group.hooks[0].to_s.must_equal "[:on_change, :change!, {}]"
|
151
163
|
# Group.hooks[1][1][:nested].hooks.to_s.must_equal "[[:on_add, [:notify_album!]],[:on_add, [:reset_song!]]]"
|
152
|
-
Group.hooks[2].to_s.must_equal "[:on_change,
|
164
|
+
Group.hooks[2].to_s.must_equal "[:on_change, :rehash_name!, {:property=>:title}]"
|
153
165
|
|
154
|
-
Group.definitions.get(Group.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change,
|
166
|
+
Group.definitions.get(Group.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change, :sing!, {}]]"
|
155
167
|
end
|
156
168
|
|
157
169
|
class EmptyGroup < Group
|
@@ -175,7 +187,7 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
|
|
175
187
|
Group.hooks.size.must_equal 4
|
176
188
|
pp EnhancedGroup.hooks
|
177
189
|
EnhancedGroup.hooks.size.must_equal 6
|
178
|
-
EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add,
|
190
|
+
EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add, :rewind!, {}]]"
|
179
191
|
end
|
180
192
|
|
181
193
|
class EnhancedWithInheritGroup < EnhancedGroup
|
@@ -191,10 +203,10 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
|
|
191
203
|
Group.hooks.size.must_equal 4
|
192
204
|
EnhancedGroup.hooks.size.must_equal 6
|
193
205
|
|
194
|
-
EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add,
|
206
|
+
EnhancedGroup.definitions.get(EnhancedGroup.hooks[5][1])[:nested].hooks.to_s.must_equal "[[:on_add, :rewind!, {}]]"
|
195
207
|
EnhancedWithInheritGroup.hooks.size.must_equal 6
|
196
|
-
EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[1][1])[:nested].hooks.to_s.must_equal "[[:on_add,
|
197
|
-
EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change,
|
208
|
+
EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[1][1])[:nested].hooks.to_s.must_equal "[[:on_add, :rewind!, {}], [:on_add, :eat!, {}]]"
|
209
|
+
EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change, :sing!, {}], [:on_delete, :yell!, {}]]"
|
198
210
|
end
|
199
211
|
|
200
212
|
class RemovingInheritGroup < Group
|
@@ -217,8 +229,8 @@ class CallbackGroupInheritanceTest < MiniTest::Spec
|
|
217
229
|
it do
|
218
230
|
Group.hooks.size.must_equal 4
|
219
231
|
RemovingInheritGroup.hooks.size.must_equal 3
|
220
|
-
RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[0][1])[:nested].hooks.to_s.must_equal "[[:on_add,
|
221
|
-
RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[2][1])[:nested].hooks.to_s.must_equal "[[:on_change,
|
232
|
+
RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[0][1])[:nested].hooks.to_s.must_equal "[[:on_add, :reset_song!, {}]]"
|
233
|
+
RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[2][1])[:nested].hooks.to_s.must_equal "[[:on_change, :sing!, {}]]"
|
222
234
|
end
|
223
235
|
|
224
236
|
# Group::clone
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: disposable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uber
|