super_callbacks 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.
data/README.md CHANGED
@@ -1,394 +1,439 @@
1
- # SuperCallbacks
2
-
3
- [![Build Status](https://travis-ci.org/jrpolidario/super_callbacks.svg?branch=master)](https://travis-ci.org/jrpolidario/super_callbacks)
4
- [![Gem Version](https://badge.fury.io/rb/super_callbacks.svg)](https://badge.fury.io/rb/super_callbacks)
5
-
6
- * Allows `before` and `after` callbacks to any Class.
7
- * Supports both class and instance level callbacks
8
- * Supports conditional callbacks
9
- * Supports inherited callbacks; hence named "Super", get it? :D haha!
10
- ---
11
- * Focuses on performance and flexibility as intended primarily for game development, and event-driven apps
12
- * Standalone; no other gem dependencies
13
- * `super_callbacks` is the upgraded version of my other repo [`dragon_ruby_callbacks`](https://github.com/jrpolidario/dragonruby_callbacks)
14
- * Heavily influenced by [Rails' ActiveSupport::Callbacks](https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html)
15
-
16
- ## Dependencies
17
-
18
- * **Ruby ~> 2.0**
19
-
20
- ## Installation
21
-
22
- Add this line to your application's Gemfile:
23
-
24
- ```ruby
25
- gem 'super_callbacks', '~> 1.0'
26
- ```
27
-
28
- And then execute:
29
-
30
- $ bundle
31
-
32
- Or install it yourself as:
33
-
34
- $ gem install super_callbacks
35
-
36
- ## Usage
37
-
38
- ### Example 1 (Block Mode)
39
-
40
- ```ruby
41
- require 'super_callbacks'
42
-
43
- class Foo
44
- # add this line inside your Class file/s
45
- include SuperCallbacks
46
-
47
- # add this block of lines
48
- before :bar do
49
- puts 'before bar!'
50
- end
51
-
52
- def bar
53
- puts 'bar!'
54
- end
55
- end
56
-
57
- foo = Foo.new
58
- foo.bar
59
- # => 'before bar!'
60
- # => 'bar!'
61
- ```
62
-
63
- *Notice above that the before block gets called first before the method `bar`*
64
-
65
- ```ruby
66
- class Foo
67
- include SuperCallbacks
68
-
69
- after :bar do
70
- puts 'after bar!'
71
- end
72
-
73
- def bar
74
- puts 'bar!'
75
- end
76
- end
77
-
78
- foo = Foo.new
79
- foo.bar
80
- # => 'bar!'
81
- # => 'after bar!'
82
- ```
83
-
84
- *Notice above that the after block gets called after the method `bar`*
85
-
86
- ### Example 2 (Method Calling)
87
-
88
- ```ruby
89
- class Foo
90
- include SuperCallbacks
91
-
92
- before :bar, :baz
93
-
94
- def bar
95
- puts 'bar!'
96
- end
97
-
98
- def baz
99
- puts 'baz!'
100
- end
101
- end
102
-
103
- foo = Foo.new
104
- foo.bar
105
- # => 'baz!'
106
- # => 'bar!'
107
- ```
108
-
109
- *Notice above that you can also call another method instead of supplying a block.*
110
-
111
- *Above uses `before`, but works similarly with `after`*
112
-
113
- ### Example 3 (Multiple Callbacks)
114
-
115
- ```ruby
116
- class Foo
117
- include SuperCallbacks
118
-
119
- before :bar, :baz_1
120
- before :bar do
121
- puts 'baz 2!'
122
- end
123
- before :bar, :baz_3
124
-
125
- def bar
126
- puts 'bar!'
127
- end
128
-
129
- def baz_1
130
- puts 'baz 1!'
131
- end
132
-
133
- def baz_3
134
- puts 'baz 3!'
135
- end
136
- end
137
-
138
- foo = Foo.new
139
- foo.bar
140
- # => 'baz 1!'
141
- # => 'bar 2!'
142
- # => 'bar 3!'
143
- # => 'bar!'
144
- ```
145
-
146
- *Notice above multiple callbacks are supported, and that they are called in firt-come-first-served order.*
147
-
148
- *Above uses `before`, but works similarly with `after`*
149
-
150
- ### Example 4 (Setter Method Callbacks)
151
-
152
- > This is the primary reason why I made this game: to handle "change-dependent" logic in my game engine
153
-
154
- ```ruby
155
- class Foo
156
- include SuperCallbacks
157
-
158
- attr_accessor :bar
159
-
160
- before :bar= do |arg|
161
- puts "@bar currently has a value of #{@bar}"
162
- puts "@bar will have a new value of #{arg}"
163
- end
164
-
165
- before :baz do |arg1, arg2|
166
- puts "baz will be called with arguments #{arg1}, #{arg2}"
167
- end
168
-
169
- def baz(x, y)
170
- puts 'baz has been called!'
171
- end
172
- end
173
-
174
- foo = Foo.new
175
- foo.bar = 5
176
- # => '@bar currently has a value of '
177
- # => '@bar will have a new value of 5'
178
- puts foo.bar
179
- # => 5
180
-
181
- foo.baz(1, 2)
182
- # => 'baz will be called with arguments 1, 2'
183
- # => 'baz has been called!'
184
- ```
185
-
186
- *Above uses `before`, but works similarly with `after`*
187
-
188
- ### Example 5 (Conditional Callbacks)
189
-
190
- ```ruby
191
- class Monster
192
- include SuperCallbacks
193
-
194
- attr_accessor :hp
195
-
196
- after :hp=, :despawn, if: -> (arg) { @hp == 0 }
197
-
198
- # above is just equivalently:
199
- # after :hp= do |arg|
200
- # despawn if @hp == 0
201
- # end
202
-
203
- def despawn
204
- puts 'despawning!'
205
- # do something here, like say removing the Monster from the world
206
- end
207
- end
208
-
209
- monster = Monster.new
210
- monster.hp = 5
211
- monster.hp -= 1 # 4
212
- monster.hp -= 1 # 3
213
- monster.hp -= 1 # 2
214
- monster.hp -= 1 # 1
215
- monster.hp -= 1 # hp is now 0, so despawn!
216
- # => despawning!
217
- ```
218
-
219
- *Above uses `after`, but works similarly with `before`*
220
-
221
- ### Example 6 (Pseudo-Skipping Callbacks)
222
-
223
- * via Ruby's [`instance_variable_get`](https://ruby-doc.org/core-1.9.1/Object.html#method-i-instance_variable_get) and [`instance_variable_set`](https://ruby-doc.org/core-1.9.1/Object.html#method-i-instance_variable_set)
224
-
225
- ```ruby
226
- class Foo
227
- include SuperCallbacks
228
-
229
- attr_accessor :bar
230
-
231
- before :bar= do |arg|
232
- puts 'before bar= is called!'
233
- end
234
- end
235
-
236
- foo = Foo.new
237
-
238
- # normal way (callbacks are called):
239
- foo.bar = 'somevalue'
240
- # => 'before_bar= is called!'
241
-
242
- # but to "pseudo" skip all callbacks, and directly manipulate the instance variable value:
243
- foo.instance_variable_set(:@bar, 'somevalue')
244
- ```
245
-
246
- *At the moment, I am not compelled (yet?) to fully support skipping callbacks because I do not want to pollute the DSL and I do not find myself yet needing such behaviour, because the callbacks are there for "integrity". If I really want the callbacks conditional, I'll just use the conditional argument.*
247
-
248
- ### Example 7 (Class and Instance Level Callbacks)
249
-
250
- ```ruby
251
- class Foo
252
- include SuperCallbacks
253
-
254
- before :bar do
255
- puts 'before bar 1!'
256
- end
257
-
258
- before :bar do
259
- puts 'before bar 2!'
260
- end
261
-
262
- def bar
263
- puts 'bar!'
264
- end
265
- end
266
-
267
- foo_1 = Foo.new
268
- foo_2 = Foo.new
269
-
270
- foo_1.before :bar do
271
- puts 'before bar 3'
272
- end
273
-
274
- foo_1.before :bar do
275
- puts 'before bar 4'
276
- end
277
-
278
- foo_1.bar
279
- # => 'before bar 1!'
280
- # => 'before bar 2!'
281
- # => 'before bar 3'
282
- # => 'before bar 4'
283
- # => 'bar!'
284
-
285
- foo_2.bar
286
- # => 'before bar 1!'
287
- # => 'before bar 2!'
288
- # => 'bar!'
289
- ```
290
-
291
- *Notice above that foo_1 and foo_2 both call the class-level callbacks, while they have independent (not-shared) instance-level callbacks defined. Order of execution is class-level first then instance-level, of which defined callbacks are then in order of first-come-first-serve.*
292
-
293
- *Above uses `before`, but works similarly with `after`*
294
-
295
- ### Example 8 (Inherited Callbacks)
296
-
297
- ```ruby
298
- class Foo
299
- include SuperCallbacks
300
-
301
- before :bar do
302
- puts 'Foo: before bar 1!'
303
- end
304
-
305
- def bar
306
- puts 'bar!'
307
- end
308
- end
309
-
310
- class SubFoo < Foo
311
- before :bar do
312
- puts 'SubFoo: bar'
313
- end
314
- end
315
-
316
- foo = Foo.new
317
- foo.bar
318
- # => 'Foo: before bar 1!'
319
- # => 'bar!'
320
-
321
- sub_foo = SubFoo.new
322
- sub_foo.bar
323
- # => 'Foo: before bar 1!'
324
- # => 'SubFoo: bar'
325
- # => 'bar!'
326
- ```
327
-
328
- *Notice above `sub_foo` calls both `before` callbacks defined in `Foo` and `SubFoo`, because SubFoo inherits from Foo. Callbacks are called in order of ancestors descending; meaning it starts calling the top-level ancestor superclass callbacks, and then calling its subclass callbacks, until it reaches the instance's class callbacks*
329
-
330
- *Above uses `before`, but works similarly with `after`*
331
-
332
- ### Example 9 (Requiring Method To Be Defined)
333
-
334
- ```ruby
335
- class Foo
336
- include SuperCallbacks
337
-
338
- after! :bar do
339
- puts 'after bar!'
340
- end
341
-
342
- def bar
343
- puts 'bar!'
344
- end
345
- end
346
- # => ArgumentError: `bar` is not or not yet defined for Foo
347
-
348
- class Foo
349
- include SuperCallbacks
350
-
351
- def bar
352
- puts 'bar!'
353
- end
354
-
355
- after! :bar do
356
- puts 'after bar!'
357
- end
358
- end
359
- # => [NO ERRORS]
360
- ```
361
-
362
- *From above, sometimes I noticed that I forgot to define a method! So the bang `!` version is just basically like `after` except that this raises an error if `method_name` is not defined or not yet defined (at the time `after!` is called). This works perfect with `attr_accesors` I normally put them at the top of the lines of a Class, and so I can now safely call `before!` or `after!` because I am sure that I already defined everything I needed to define. If I forgot something then, this `before!` would raise an error and alert me, and not silently failing. Helps debugging :)*
363
-
364
- *Above uses `after!`, but works similarly with `before!`*
365
-
366
- ## TODOs
367
- * when the need already arises, implement `around` (If you have ideas or want to help this part, please feel free to fork or send me a message! :)
368
-
369
- ## Development
370
-
371
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
372
-
373
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
374
-
375
- ## Contributing
376
-
377
- Bug reports and pull requests are welcome on GitHub at https://github.com/jrpolidario/super_callbacks. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
378
-
379
- ## License
380
-
381
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
382
-
383
- ## Changelog
384
-
385
- * 1.0.3 (2019-08-12)
386
- * Cleaner code without explicitly calling `run_callbacks` anymore; done now because of ruby upgrade from 1.9 to 2.0+ which already supports `prepend`
387
- * Supported both class and instance level callbacks
388
- * Supported inherited callbacks
389
- * v0.2.1 (2019-08-09) *From `dragonruby_callbacks`*
390
- * Fixed syntax errors for ruby 1.9.3; Fixed not supporting subclasses of Proc, String, or Symbol
391
- * v0.2 (2019-08-08) *From `dragonruby_callbacks`*
392
- * Supported [conditional callbacks](#conditional-callbacks) with `:if`
393
- * v0.1 (2019-08-07) *From `dragonruby_callbacks`*
394
- * Done all
1
+ # SuperCallbacks
2
+
3
+ [![Build Status](https://travis-ci.org/jrpolidario/super_callbacks.svg?branch=master)](https://travis-ci.org/jrpolidario/super_callbacks)
4
+ [![Gem Version](https://badge.fury.io/rb/super_callbacks.svg)](https://badge.fury.io/rb/super_callbacks)
5
+
6
+ * Allows `before` and `after` callbacks to any Class.
7
+ * Supports "dirty" checking of instance variables changes
8
+ * Supports both class and instance level callbacks
9
+ * Supports conditional callbacks
10
+ * Supports inherited callbacks; hence named "Super", get it? :D haha!
11
+ ---
12
+ * Focuses on performance and flexibility as intended primarily for game development, and event-driven apps
13
+ * Standalone; no other gem dependencies
14
+ * `super_callbacks` is the upgraded version of my other repo [`dragonruby_callbacks`](https://github.com/jrpolidario/dragonruby_callbacks)
15
+ * Heavily influenced by [Rails' ActiveSupport::Callbacks](https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html)
16
+
17
+ ## Dependencies
18
+
19
+ * **Ruby ~> 2.0**
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'super_callbacks', '~> 1.1'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install super_callbacks
36
+
37
+ ## Usage
38
+
39
+ ### Example 1 (Block Mode)
40
+
41
+ ```ruby
42
+ require 'super_callbacks'
43
+
44
+ class Foo
45
+ # add this line inside your Class file/s
46
+ include SuperCallbacks
47
+
48
+ # add this block of lines
49
+ before :bar do
50
+ puts 'before bar!'
51
+ end
52
+
53
+ def bar
54
+ puts 'bar!'
55
+ end
56
+ end
57
+
58
+ foo = Foo.new
59
+ foo.bar
60
+ # => 'before bar!'
61
+ # => 'bar!'
62
+ ```
63
+
64
+ *Notice above that the before block gets called first before the method `bar`*
65
+
66
+ ```ruby
67
+ class Foo
68
+ include SuperCallbacks
69
+
70
+ after :bar do
71
+ puts 'after bar!'
72
+ end
73
+
74
+ def bar
75
+ puts 'bar!'
76
+ end
77
+ end
78
+
79
+ foo = Foo.new
80
+ foo.bar
81
+ # => 'bar!'
82
+ # => 'after bar!'
83
+ ```
84
+
85
+ *Notice above that the after block gets called after the method `bar`*
86
+
87
+ ### Example 2 (Method Calling)
88
+
89
+ ```ruby
90
+ class Foo
91
+ include SuperCallbacks
92
+
93
+ before :bar, :baz
94
+
95
+ def bar
96
+ puts 'bar!'
97
+ end
98
+
99
+ def baz
100
+ puts 'baz!'
101
+ end
102
+ end
103
+
104
+ foo = Foo.new
105
+ foo.bar
106
+ # => 'baz!'
107
+ # => 'bar!'
108
+ ```
109
+
110
+ *Notice above that you can also call another method instead of supplying a block.*
111
+
112
+ *Above uses `before`, but works similarly with `after`*
113
+
114
+ ### Example 3 (Multiple Callbacks)
115
+
116
+ ```ruby
117
+ class Foo
118
+ include SuperCallbacks
119
+
120
+ before :bar, :baz_1
121
+ before :bar do
122
+ puts 'baz 2!'
123
+ end
124
+ before :bar, :baz_3
125
+
126
+ def bar
127
+ puts 'bar!'
128
+ end
129
+
130
+ def baz_1
131
+ puts 'baz 1!'
132
+ end
133
+
134
+ def baz_3
135
+ puts 'baz 3!'
136
+ end
137
+ end
138
+
139
+ foo = Foo.new
140
+ foo.bar
141
+ # => 'baz 1!'
142
+ # => 'bar 2!'
143
+ # => 'bar 3!'
144
+ # => 'bar!'
145
+ ```
146
+
147
+ *Notice above multiple callbacks are supported, and that they are called in firt-come-first-served order.*
148
+
149
+ *Above uses `before`, but works similarly with `after`*
150
+
151
+ ### Example 4 (Setter Method Callbacks)
152
+
153
+ > This is the primary reason why I made this: to handle "change-dependent" logic in my game engine
154
+
155
+ ```ruby
156
+ class Foo
157
+ include SuperCallbacks
158
+
159
+ attr_accessor :bar
160
+
161
+ before :bar= do |arg|
162
+ puts "@bar currently has a value of #{@bar}"
163
+ puts "@bar will have a new value of #{arg}"
164
+ end
165
+
166
+ before :baz do |arg1, arg2|
167
+ puts "baz will be called with arguments #{arg1}, #{arg2}"
168
+ end
169
+
170
+ def baz(x, y)
171
+ puts 'baz has been called!'
172
+ end
173
+ end
174
+
175
+ foo = Foo.new
176
+ foo.bar = 5
177
+ # => '@bar currently has a value of '
178
+ # => '@bar will have a new value of 5'
179
+ puts foo.bar
180
+ # => 5
181
+
182
+ foo.baz(1, 2)
183
+ # => 'baz will be called with arguments 1, 2'
184
+ # => 'baz has been called!'
185
+ ```
186
+
187
+ *Above uses `before`, but works similarly with `after`*
188
+
189
+ ### Example 5 (Conditional Callbacks)
190
+
191
+ ```ruby
192
+ class Monster
193
+ include SuperCallbacks
194
+
195
+ attr_accessor :hp
196
+
197
+ after :hp=, :despawn, if: -> (arg) { @hp == 0 }
198
+
199
+ # above is just equivalently:
200
+ # after :hp= do |arg|
201
+ # despawn if @hp == 0
202
+ # end
203
+
204
+ def despawn
205
+ puts 'despawning!'
206
+ # do something here, like say removing the Monster from the world
207
+ end
208
+ end
209
+
210
+ monster = Monster.new
211
+ monster.hp = 5
212
+ monster.hp -= 1 # 4
213
+ monster.hp -= 1 # 3
214
+ monster.hp -= 1 # 2
215
+ monster.hp -= 1 # 1
216
+ monster.hp -= 1 # hp is now 0, so despawn!
217
+ # => despawning!
218
+ ```
219
+
220
+ *Above uses `after`, but works similarly with `before`*
221
+
222
+ ### Example 6 (Pseudo-Skipping Callbacks)
223
+
224
+ * via Ruby's [`instance_variable_get`](https://ruby-doc.org/core-1.9.1/Object.html#method-i-instance_variable_get) and [`instance_variable_set`](https://ruby-doc.org/core-1.9.1/Object.html#method-i-instance_variable_set)
225
+
226
+ ```ruby
227
+ class Foo
228
+ include SuperCallbacks
229
+
230
+ attr_accessor :bar
231
+
232
+ before :bar= do |arg|
233
+ puts 'before bar= is called!'
234
+ end
235
+ end
236
+
237
+ foo = Foo.new
238
+
239
+ # normal way (callbacks are called):
240
+ foo.bar = 'somevalue'
241
+ # => 'before_bar= is called!'
242
+
243
+ # but to "pseudo" skip all callbacks, and directly manipulate the instance variable value:
244
+ foo.instance_variable_set(:@bar, 'somevalue')
245
+ ```
246
+
247
+ *At the moment, I am not compelled (yet?) to fully support skipping callbacks because I do not want to pollute the DSL and I do not find myself yet needing such behaviour, because the callbacks are there for "integrity". If I really want the callbacks conditional, I'll just use the conditional argument.*
248
+
249
+ ### Example 7 (Class and Instance Level Callbacks)
250
+
251
+ ```ruby
252
+ class Foo
253
+ include SuperCallbacks
254
+
255
+ before :bar do
256
+ puts 'before bar 1!'
257
+ end
258
+
259
+ before :bar do
260
+ puts 'before bar 2!'
261
+ end
262
+
263
+ def bar
264
+ puts 'bar!'
265
+ end
266
+ end
267
+
268
+ foo_1 = Foo.new
269
+ foo_2 = Foo.new
270
+
271
+ foo_1.before :bar do
272
+ puts 'before bar 3'
273
+ end
274
+
275
+ foo_1.before :bar do
276
+ puts 'before bar 4'
277
+ end
278
+
279
+ foo_1.bar
280
+ # => 'before bar 1!'
281
+ # => 'before bar 2!'
282
+ # => 'before bar 3'
283
+ # => 'before bar 4'
284
+ # => 'bar!'
285
+
286
+ foo_2.bar
287
+ # => 'before bar 1!'
288
+ # => 'before bar 2!'
289
+ # => 'bar!'
290
+ ```
291
+
292
+ *Notice above that foo_1 and foo_2 both call the class-level callbacks, while they have independent (not-shared) instance-level callbacks defined. Order of execution is class-level first then instance-level, of which defined callbacks are then in order of first-come-first-serve.*
293
+
294
+ *Above uses `before`, but works similarly with `after`*
295
+
296
+ ### Example 8 (Inherited Callbacks)
297
+
298
+ ```ruby
299
+ class Foo
300
+ include SuperCallbacks
301
+
302
+ before :bar do
303
+ puts 'Foo: before bar 1!'
304
+ end
305
+
306
+ def bar
307
+ puts 'bar!'
308
+ end
309
+ end
310
+
311
+ class SubFoo < Foo
312
+ before :bar do
313
+ puts 'SubFoo: bar'
314
+ end
315
+ end
316
+
317
+ foo = Foo.new
318
+ foo.bar
319
+ # => 'Foo: before bar 1!'
320
+ # => 'bar!'
321
+
322
+ sub_foo = SubFoo.new
323
+ sub_foo.bar
324
+ # => 'Foo: before bar 1!'
325
+ # => 'SubFoo: bar'
326
+ # => 'bar!'
327
+ ```
328
+
329
+ *Notice above `sub_foo` calls both `before` callbacks defined in `Foo` and `SubFoo`, because SubFoo inherits from Foo. Callbacks are called in order of ancestors descending; meaning it starts calling the top-level ancestor superclass callbacks, and then calling its subclass callbacks, until it reaches the instance's class callbacks*
330
+
331
+ *Above uses `before`, but works similarly with `after`*
332
+
333
+ ### Example 9 (Requiring Method To Be Defined)
334
+
335
+ ```ruby
336
+ class Foo
337
+ include SuperCallbacks
338
+
339
+ after! :bar do
340
+ puts 'after bar!'
341
+ end
342
+
343
+ def bar
344
+ puts 'bar!'
345
+ end
346
+ end
347
+ # => ArgumentError: `bar` is not or not yet defined for Foo
348
+
349
+ class Foo
350
+ include SuperCallbacks
351
+
352
+ def bar
353
+ puts 'bar!'
354
+ end
355
+
356
+ after! :bar do
357
+ puts 'after bar!'
358
+ end
359
+ end
360
+ # => [NO ERRORS]
361
+ ```
362
+
363
+ *From above, sometimes I noticed that I forgot to define a method! So the bang `!` version is just basically like `after` except that this raises an error if `method_name` is not defined or not yet defined (at the time `after!` is called). This works perfect with `attr_accesors` I normally put them at the top of the lines of a Class, and so I can now safely call `before!` or `after!` because I am sure that I already defined everything I needed to define. If I forgot something then, this `before!` would raise an error and alert me, and not silently failing. Helps debugging :)*
364
+
365
+ *Above uses `after!`, but works similarly with `before!`*
366
+
367
+ ### Example 10 (Dirty Checking of Instance Variables Changes)
368
+
369
+ ```ruby
370
+ class Foo
371
+ include SuperCallbacks
372
+
373
+ attr_accessor :bar, :baz
374
+
375
+ after :bar= do |arg|
376
+ puts 'original values of all instance attributes:'
377
+ puts instance_variables_before_change
378
+
379
+ puts 'original value:'
380
+ puts instance_variable_before_change :@bar
381
+
382
+ if instance_variable_changed? :@bar
383
+ puts 'new value'
384
+ @arg
385
+ end
386
+ end
387
+ end
388
+
389
+ foo = Foo.new
390
+ foo.bar = 1 # bar is changed from nil to 1
391
+ # => original values of all instance attributes:
392
+ # => {}
393
+ # => original value:
394
+ # => nil
395
+ # => new value:
396
+ # => 1
397
+ foo.bar = 1 # bar is not changed from 1 to 1
398
+ # => original values of all instance attributes:
399
+ # => { :@bar => 1 }
400
+ # => original value:
401
+ # => 1
402
+ ```
403
+
404
+ *Notice above on the second time `foo.bar = 1` is called, "new value" was no longer "puts", because `@bar` didn't change from 1 to 1. You can only use `instance_variables_before_change`, instance_variable_before_change` and `instance_variable_changed?` inside the SuperCallback cycle; otherwise you will get a `"You cannot call this method outside the SuperCallback cycle"` error.
405
+
406
+ *Above uses `after!`, but works similarly with `before!`*
407
+
408
+ ## TODOs
409
+ * when the need already arises, implement `around` (If you have ideas or want to help this part, please feel free to fork or send me a message! :)
410
+ * [Found a new bug I could not solve](https://github.com/jrpolidario/super_callbacks/issues/1). If you have any ideas how to solve this, please feel to submit a merge request! :) At the moment, this is not important to me (yet?) as I develop my game engine, so I'm leaving this here for now, and I'll come back again into this later.
411
+
412
+ ## Development
413
+
414
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
415
+
416
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
417
+
418
+ ## Contributing
419
+
420
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jrpolidario/super_callbacks. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
421
+
422
+ ## License
423
+
424
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
425
+
426
+ ## Changelog
427
+
428
+ * 1.1.0 (2019-08-14)
429
+ * [Supported "dirty" checking of instance variable changes](#example-10-dirty-checking-of-instance-variables-changes)
430
+ * 1.0.3 (2019-08-12)
431
+ * Cleaner code without explicitly calling `run_callbacks` anymore; done now because of ruby upgrade from 1.9 to 2.0+ which already supports `prepend`
432
+ * Supported both class and instance level callbacks
433
+ * Supported inherited callbacks
434
+ * v0.2.1 (2019-08-09) *From `dragonruby_callbacks`*
435
+ * Fixed syntax errors for ruby 1.9.3; Fixed not supporting subclasses of Proc, String, or Symbol
436
+ * v0.2 (2019-08-08) *From `dragonruby_callbacks`*
437
+ * Supported [conditional callbacks](#conditional-callbacks) with `:if`
438
+ * v0.1 (2019-08-07) *From `dragonruby_callbacks`*
439
+ * Done all