disposable 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 78adbe70c077a4e207d4cd692e4478a61184e1bf
4
- data.tar.gz: 64ab6c7d7881a7c075e845ee09cf33363a78bd58
3
+ metadata.gz: 31d57820d95d0f0c679a690f4f5571fecbe972d4
4
+ data.tar.gz: 9ca35177d6953ebdc3fc2d3b8d7f2040177586ef
5
5
  SHA512:
6
- metadata.gz: 2580b1e00e75d27ff341b987b36662f162f45b5c6510be8043021f69f028f0dc9502727d9bc56fcfbc26ebdf8af7b26b3efafff7ab37953ba9077de06fdfd873
7
- data.tar.gz: c8a0b0502156538666b9d811ec185818ea2bde1a13274483c2bc514b872cf0112319f188ae3865fe7f48eae81458ec27bf1fb7885a8705a96175d0f32bb086df
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
@@ -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][0] == callback }
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 |*args|
61
- heritage.record(event, *args)
60
+ define_method event do |method, options={}|
61
+ heritage.record(event, method, options)
62
62
 
63
- hooks << [event.to_sym, args]
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, args|
70
+ self.class.hooks.each do |event, method, property_options|
71
71
  if event == "property" # FIXME: make nicer.
72
- definition = self.class.definitions.get(args)
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, args)
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
- method = args[0]
90
- context = options[:context] || self # TODO: test me.
91
-
92
- options = args[1..-1]
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
- # TODO: Use Option::Value here.
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, *args, &block) # FIXME: as long as we only support method, pass in here.
109
- send(event, *args, &block)
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.nil?
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(options={}, &block)
151
- name = options[:property]
152
+ def on_change(property_options={}, &block)
153
+ name = property_options[:property]
152
154
 
153
155
  @twins.each do |twin|
154
156
  if name
@@ -1,3 +1,3 @@
1
1
  module Disposable
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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
- @output = "added to songs"
17
+ def notify_album!(twin, options)
18
+ options[:content] << "notify_album!"
19
19
  end
20
20
 
21
- def reset_song!(twin)
22
- @output << "added to songs, reseting"
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
- @output = "changed!"
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 notify_album!(twin)
102
- @output << "notify_album!"
113
+ def rehash_name!(twin, options)
114
+ options[:content] << "Op: rehash_name! [#{options[:context].class}]"
103
115
  end
104
116
 
105
- def reset_song!(twin)
106
- @output << "reset_song!"
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
- context.output.must_equal "changed!notify_album!reset_song!"
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, [: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, [:rehash_name!, {:property=>:title}]]"
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, [:sing!]]]"
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, [:rewind!]]]"
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, [:rewind!]]]"
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, [:rewind!]], [:on_add, [:eat!]]]"
197
- EnhancedWithInheritGroup.definitions.get(EnhancedWithInheritGroup.hooks[3][1])[:nested].hooks.to_s.must_equal "[[:on_change, [:sing!]], [:on_delete, [:yell!]]]"
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, [:reset_song!]]]"
221
- RemovingInheritGroup.definitions.get(RemovingInheritGroup.hooks[2][1])[:nested].hooks.to_s.must_equal "[[:on_change, [:sing!]]]"
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.0
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-26 00:00:00.000000000 Z
11
+ date: 2015-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uber