u-observers 1.0.0 → 2.3.0

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
  SHA256:
3
- metadata.gz: 4c90f3338948cf8db02bdb1a882e3191adfd52f106fc2b4c1acf873447abd82a
4
- data.tar.gz: 2db659fbaee101e1af2838bdb89dc85838f0e9686d14fe14fd9782fc568ee1f6
3
+ metadata.gz: 55ea9f6a206dba9526be1d7777969b26311f725652b3020344db33563a5835c8
4
+ data.tar.gz: d8a6e1bf2e73d15fadbd71e82aa17e0c511fb11d97a7839ba165c50589324b66
5
5
  SHA512:
6
- metadata.gz: 674b8dabdc6cfca0a982c1f72582bf1fcaab34ead0f0de29d4975cc62e164c13bbded5e6118152951584fb5855b6c539510ca393b36f9cf56622bf663d7b22e2
7
- data.tar.gz: ff1e33f5029a40745172c7196d7e21552e8f4d534c71f057bf5643e3262fe8fa243fb55219eed352195a09abc51c337476f9f8bfcd5bce5f61cee416c2ec8de7
6
+ metadata.gz: c9b907879c02a2071b6c194af9f5c1a6e50a3bd17655beaed0f9dfb7858c892f657c9a57666d320d23d0055a48625d168d625fbae19ca7a560722b8c1b475d31
7
+ data.tar.gz: 4a551b0a43d15b5968d843d2a3b737ae245e177da3ac0c595f9265be887ff3b2b1205a3544c368973cae993869a9083fbffdc2cf64dab9b18c5d6d17eae5282b
data/README.md CHANGED
@@ -26,17 +26,30 @@
26
26
 
27
27
  This gem implements the observer pattern [[1]](https://en.wikipedia.org/wiki/Observer_pattern)[[2]](https://refactoring.guru/design-patterns/observer) (also known as publish/subscribe). It provides a simple mechanism for one object to inform a set of interested third-party objects when its state changes.
28
28
 
29
- Ruby's standard library [has an abstraction](https://ruby-doc.org/stdlib-2.7.1/libdoc/observer/rdoc/Observable.html) that enables you to use this pattern. But its design can conflict with other mainstream libraries, like the [`ActiveModel`/`ActiveRecord`](https://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-changed), which also has the [`changed`](https://ruby-doc.org/stdlib-2.7.1/libdoc/observer/rdoc/Observable.html#method-i-changed) method. In this case, the behavior of the Stdlib will be been compromised.
29
+ Ruby's standard library [has an abstraction](https://ruby-doc.org/stdlib-2.7.1/libdoc/observer/rdoc/Observable.html) that enables you to use this pattern. But its design can conflict with other mainstream libraries, like the [`ActiveModel`/`ActiveRecord`](https://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-changed), which also has the [`changed`](https://ruby-doc.org/stdlib-2.7.1/libdoc/observer/rdoc/Observable.html#method-i-changed) method. In this case, the behavior of the Stdlib will be compromised.
30
30
 
31
- Because of this issue, I decided to create a gem that encapsulates the pattern without changing the object's implementation so much. The `Micro::Observers` includes just one instance method in the target class (its instance will be the observed subject).
31
+ Because of this issue, I decided to create a gem that encapsulates the pattern without changing the object's implementation so much. The `Micro::Observers` includes just one instance method in the target class (its instance will be the observed subject/object).
32
+
33
+ > **Note:** Você entende português? 🇧🇷 🇵🇹 Verifique o [README traduzido em pt-BR](https://github.com/serradura/u-observers/blob/main/README.pt-BR.md).
32
34
 
33
35
  # Table of contents <!-- omit in toc -->
34
36
  - [Installation](#installation)
35
37
  - [Compatibility](#compatibility)
36
38
  - [Usage](#usage)
37
- - [Passing a context for your observers](#passing-a-context-for-your-observers)
39
+ - [Sharing a context with your observers](#sharing-a-context-with-your-observers)
40
+ - [Sharing data when notifying the observers](#sharing-data-when-notifying-the-observers)
41
+ - [What is a `Micro::Observers::Event`?](#what-is-a-microobserversevent)
42
+ - [Using a callable as an observer](#using-a-callable-as-an-observer)
38
43
  - [Calling the observers](#calling-the-observers)
39
44
  - [Notifying observers without marking them as changed](#notifying-observers-without-marking-them-as-changed)
45
+ - [Defining observers that execute only once](#defining-observers-that-execute-only-once)
46
+ - [`observers.attach(*args, perform_once: true)`](#observersattachargs-perform_once-true)
47
+ - [`observers.once(event:, call:, ...)`](#observersonceevent-call-)
48
+ - [Defining observers using blocks](#defining-observers-using-blocks)
49
+ - [order.observers.on()](#orderobserverson)
50
+ - [order.observers.on()](#orderobserverson-1)
51
+ - [Replacing a block by a `lambda`/`proc`](#replacing-a-block-by-a-lambdaproc)
52
+ - [Detaching observers](#detaching-observers)
40
53
  - [ActiveRecord and ActiveModel integrations](#activerecord-and-activemodel-integrations)
41
54
  - [notify_observers_on()](#notify_observers_on)
42
55
  - [notify_observers()](#notify_observers)
@@ -57,11 +70,13 @@ gem 'u-observers'
57
70
 
58
71
  | u-observers | branch | ruby | activerecord |
59
72
  | ----------- | ------- | -------- | ------------- |
60
- | 1.0.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
73
+ | unreleased | main | >= 2.2.0 | >= 3.2, < 6.1 |
74
+ | 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, < 6.1 |
75
+ | 1.0.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
61
76
 
62
77
  > **Note**: The ActiveRecord isn't a dependency, but you could add a module to enable some static methods that were designed to be used with its [callbacks](https://guides.rubyonrails.org/active_record_callbacks.html).
63
78
 
64
- [⬆️ Back to Top](#table-of-contents-)
79
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
65
80
 
66
81
  ## Usage
67
82
 
@@ -102,8 +117,8 @@ end
102
117
  order = Order.new
103
118
  #<Order:0x00007fb5dd8fce70 @code="X0o9yf1GsdQFvLR4", @status=:draft>
104
119
 
105
- order.observers.attach(OrderEvents) # attaching multiple observers. e.g. observers.attach(A, B, C)
106
- # <#Micro::Observers::Manager @subject=#<Order:0x00007fb5dd8fce70> @subject_changed=false @subscribers=[OrderEvents]
120
+ order.observers.attach(OrderEvents) # attaching multiple observers. e.g. observers.attach(A, B, C)
121
+ # <#Micro::Observers::Set @subject=#<Order:0x00007fb5dd8fce70> @subject_changed=false @subscribers=[OrderEvents]>
107
122
 
108
123
  order.canceled?
109
124
  # false
@@ -114,11 +129,20 @@ order.cancel!
114
129
 
115
130
  order.canceled?
116
131
  # true
132
+
133
+ order.observers.detach(OrderEvents) # detaching multiple observers. e.g. observers.detach(A, B, C)
134
+ # <#Micro::Observers::Set @subject=#<Order:0x00007fb5dd8fce70> @subject_changed=false @subscribers=[]>
135
+
136
+ order.canceled?
137
+ # true
138
+
139
+ order.observers.subject_changed!
140
+ order.observers.notify(:canceled) # nothing will happen, because there are no observers attached.
117
141
  ```
118
142
 
119
143
  **Highlights of the previous example:**
120
144
 
121
- To avoid an undesired behavior, do you need to mark the subject as changed before notify your observers about some event.
145
+ To avoid an undesired behavior, you need to mark the subject as changed before notifying your observers about some event.
122
146
 
123
147
  You can do this when using the `#subject_changed!` method. It will automatically mark the subject as changed.
124
148
 
@@ -131,11 +155,13 @@ order.observers.notify
131
155
  # ArgumentError (no events (expected at least 1))
132
156
  ```
133
157
 
134
- [⬆️ Back to Top](#table-of-contents-)
158
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
135
159
 
136
- ### Passing a context for your observers
160
+ ### Sharing a context with your observers
137
161
 
138
- To pass a context (any kind of Ruby object) for one or more observers, you will need to use the `context:` keyword as the last argument of the `#attach` method.
162
+ To share a context value (any kind of Ruby object) with one or more observers, you will need to use the `:context` keyword as the last argument of the `#attach` method. This feature gives you a unique opportunity to share a value in the attaching moment.
163
+
164
+ When the observer method receives two arguments, the first one will be the subject, and the second one an instance of `Micro::Observers::Event` that will have the given context value.
139
165
 
140
166
  ```ruby
141
167
  class Order
@@ -149,24 +175,113 @@ class Order
149
175
  end
150
176
 
151
177
  module OrderEvents
152
- def self.canceled(order, context)
153
- puts "The order #(#{order.code}) has been canceled. (from: #{context[:from]})"
178
+ def self.canceled(order, event)
179
+ puts "The order #(#{order.object_id}) has been canceled. (from: #{event.context[:from]})" # event.ctx is an alias for event.context
154
180
  end
155
181
  end
156
182
 
157
183
  order = Order.new
158
- order.observers.attach(OrderEvents, context: { from: 'example #2' ) # attaching multiple observers. e.g. observers.attach(A, B, context: {hello: :world})
184
+ order.observers.attach(OrderEvents, context: { from: 'example #2' }) # attaching multiple observers. e.g. observers.attach(A, B, context: {hello: :world})
159
185
  order.cancel!
160
186
  # The message below will be printed by the observer (OrderEvents):
161
187
  # The order #(70196221441820) has been canceled. (from: example #2)
162
188
  ```
163
189
 
164
- [⬆️ Back to Top](#table-of-contents-)
190
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
191
+
192
+ ### Sharing data when notifying the observers
193
+
194
+ As previously mentioned, the [`event context`](#sharing-a-context-with-your-observers) is a value that is stored when you attach your observer. But sometimes, it will be useful to send some additional data when broadcasting an event to the observers. The `event data` gives you this unique opportunity to share some value at the the notification moment.
195
+
196
+ ```ruby
197
+ class Order
198
+ include Micro::Observers
199
+ end
200
+
201
+ module OrderHandler
202
+ def self.changed(order, event)
203
+ puts "The order #(#{order.object_id}) received the number #{event.data} from #{event.ctx[:from]}."
204
+ end
205
+ end
206
+
207
+ order = Order.new
208
+ order.observers.attach(OrderHandler, context: { from: 'example #3' })
209
+ order.observers.subject_changed!
210
+ order.observers.notify(:changed, data: 1)
211
+ # The message below will be printed by the observer (OrderHandler):
212
+ # The order #(70196221441820) received the number 1 from example #3.
213
+ ```
214
+
215
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
216
+
217
+ ### What is a `Micro::Observers::Event`?
218
+
219
+ The `Micro::Observers::Event` is the event payload. Follow below all of its properties:
220
+
221
+ - `#name` will be the broadcasted event.
222
+ - `#subject` will be the observed subject.
223
+ - `#context` will be [the context data](#sharing-a-context-with-your-observers) that was defined in the moment that you attach the observer.
224
+ - `#data` will be [the value that was shared in the observers' notification](#sharing-data-when-notifying-the-observers).
225
+ - `#ctx` is an alias for the `#context` method.
226
+ - `#subj` is an alias for the `#subject` method.
227
+
228
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
229
+
230
+ ### Using a callable as an observer
231
+
232
+ The `observers.on()` method enables you to attach a callable as an observer.
233
+
234
+ Usually, a callable has a well-defined responsibility (do only one thing), because of this, it tends to be more [SRP (Single-responsibility principle)](https://en.wikipedia.org/wiki/Single-responsibility_principle). friendly than a conventional observer (that could have N methods to respond to different kinds of notification).
235
+
236
+ This method receives the below options:
237
+ 1. `:event` the expected event name.
238
+ 2. `:call` the callable object itself.
239
+ 3. `:with` (optional) it can define the value which will be used as the callable object's argument. So, if it is a `Proc`, a `Micro::Observers::Event` instance will be received as the `Proc` argument, and its output will be the callable argument. But if this option wasn't defined, the `Micro::Observers::Event` instance will be the callable argument.
240
+ 4. `:context` will be the context data that was defined in the moment that you attach the observer.
241
+
242
+ ```ruby
243
+ class Person
244
+ include Micro::Observers
245
+
246
+ attr_reader :name
247
+
248
+ def initialize(name)
249
+ @name = name
250
+ end
251
+
252
+ def name=(new_name)
253
+ return unless observers.subject_changed(new_name != @name)
254
+
255
+ @name = new_name
256
+
257
+ observers.notify(:name_has_been_changed)
258
+ end
259
+ end
260
+
261
+ PrintPersonName = -> (data) do
262
+ puts("Person name: #{data.fetch(:person).name}, number: #{data.fetch(:number)}")
263
+ end
264
+
265
+ person = Person.new('Rodrigo')
266
+
267
+ person.observers.on(
268
+ event: :name_has_been_changed,
269
+ call: PrintPersonName,
270
+ with: -> event { {person: event.subject, number: event.context} },
271
+ context: rand
272
+ )
273
+
274
+ person.name = 'Serradura'
275
+ # The message below will be printed by the observer (PrintPersonName):
276
+ # Person name: Serradura, number: 0.5018509191706862
277
+ ```
278
+
279
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
165
280
 
166
281
  ### Calling the observers
167
282
 
168
283
  You can use a callable (a class, module, or object that responds to the call method) to be your observers.
169
- To do this, you only need make use of the method `#call` instead of `#notify`.
284
+ To do this, you only need to make use of the method `#call` instead of `#notify`.
170
285
 
171
286
  ```ruby
172
287
  class Order
@@ -179,18 +294,18 @@ class Order
179
294
  end
180
295
  end
181
296
 
182
- OrderCancellation = -> (order) { puts "The order #(#{order.object_id}) has been canceled." }
297
+ NotifyAfterCancel = -> (order) { puts "The order #(#{order.object_id}) has been canceled." }
183
298
 
184
299
  order = Order.new
185
- order.observers.attach(OrderCancellation)
300
+ order.observers.attach(NotifyAfterCancel)
186
301
  order.cancel!
187
- # The message below will be printed by the observer (OrderEvents):
302
+ # The message below will be printed by the observer (NotifyAfterCancel):
188
303
  # The order #(70196221441820) has been canceled.
189
304
  ```
190
305
 
191
- PS: The `observers.call` can receive one or more events, but in this case, the default event (`call`) won't be transmitted.a
306
+ > **Note**: The `observers.call` can receive one or more events, but in this case, the default event (`call`) won't be transmitted.
192
307
 
193
- [⬆️ Back to Top](#table-of-contents-)
308
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
194
309
 
195
310
  ### Notifying observers without marking them as changed
196
311
 
@@ -198,11 +313,188 @@ This feature needs to be used with caution!
198
313
 
199
314
  If you use the methods `#notify!` or `#call!` you won't need to mark observers with `#subject_changed`.
200
315
 
201
- [⬆️ Back to Top](#table-of-contents-)
316
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
317
+
318
+ ### Defining observers that execute only once
319
+
320
+ There are two ways to attach an observer and define it to be performed only once.
321
+
322
+ The first way to do this is passing the `perform_once: true` option to the `observers.attach()` method. e.g.
323
+
324
+ #### `observers.attach(*args, perform_once: true)`
325
+
326
+ ```ruby
327
+ class Order
328
+ include Micro::Observers
329
+
330
+ def cancel!
331
+ observers.notify!(:canceled)
332
+ end
333
+ end
334
+
335
+ module OrderNotifications
336
+ def self.canceled(order)
337
+ puts "The order #(#{order.object_id}) has been canceled."
338
+ end
339
+ end
340
+
341
+ order = Order.new
342
+ order.observers.attach(OrderNotifications, perform_once: true) # you can also pass an array of observers with this option
343
+
344
+ order.observers.some? # true
345
+ order.cancel! # The order #(70291642071660) has been canceled.
346
+
347
+ order.observers.some? # false
348
+ order.cancel! # Nothing will happen because there aren't observers.
349
+ ```
350
+
351
+ #### `observers.once(event:, call:, ...)`
352
+
353
+ The second way to achieve this is using `observers.once()` that has the same API of [`observers.on()`](#using-a-callable-as-an-observer). But the difference of the `#once()` method is that it will remove the observer after its execution.
354
+
355
+ ```ruby
356
+ class Order
357
+ include Micro::Observers
358
+
359
+ def cancel!
360
+ observers.notify!(:canceled)
361
+ end
362
+ end
363
+
364
+ module NotifyAfterCancel
365
+ def self.call(event)
366
+ puts "The order #(#{event.subject.object_id}) has been canceled."
367
+ end
368
+ end
369
+
370
+ order = Order.new
371
+ order.observers.once(event: :canceled, call: NotifyAfterCancel)
372
+
373
+ order.observers.some? # true
374
+ order.cancel! # The order #(70301497466060) has been canceled.
375
+
376
+ order.observers.some? # false
377
+ order.cancel! # Nothing will happen because there aren't observers.
378
+ ```
379
+
380
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
381
+
382
+ ### Defining observers using blocks
383
+
384
+ The methods `#on()` and `#once()` can receive the event name (a `symbol`) and a block to define observers.
385
+
386
+ #### order.observers.on()
387
+
388
+ ```ruby
389
+ class Order
390
+ include Micro::Observers
391
+
392
+ def cancel!
393
+ observers.notify!(:canceled)
394
+ end
395
+ end
396
+
397
+ order = Order.new
398
+ order.observers.on(:canceled) do |event|
399
+ puts "The order #(#{event.subject.object_id}) has been canceled."
400
+ end
401
+
402
+ order.observers.some? # true
403
+
404
+ order.cancel! # The order #(70301497466060) has been canceled.
405
+
406
+ order.observers.some? # true
407
+ ```
408
+
409
+ #### order.observers.on()
410
+
411
+ ```ruby
412
+ class Order
413
+ include Micro::Observers
414
+
415
+ def cancel!
416
+ observers.notify!(:canceled)
417
+ end
418
+ end
419
+
420
+ order = Order.new
421
+ order.observers.once(:canceled) do |event|
422
+ puts "The order #(#{event.subject.object_id}) has been canceled."
423
+ end
424
+
425
+ order.observers.some? # true
426
+
427
+ order.cancel! # The order #(70301497466060) has been canceled.
428
+
429
+ order.observers.some? # false
430
+ ```
431
+
432
+ #### Replacing a block by a `lambda`/`proc`
433
+
434
+ Ruby allows you to replace any block with a `lambda`/`proc`. e.g.
435
+
436
+ ```ruby
437
+ class Order
438
+ include Micro::Observers
439
+
440
+ def cancel!
441
+ observers.notify!(:canceled)
442
+ end
443
+ end
444
+
445
+ NotifyAfterCancel = -> event { puts "The order #(#{event.subject.object_id}) has been canceled." }
446
+
447
+ order = Order.new
448
+ order.observers.once(:canceled, &NotifyAfterCancel)
449
+
450
+ order.observers.some? # true
451
+ order.cancel! # The order #(70301497466060) has been canceled.
452
+
453
+ order.observers.some? # false
454
+ order.cancel! # Nothing will happen because there aren't observers.
455
+ ```
456
+
457
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
458
+
459
+ ### Detaching observers
460
+
461
+ As shown in the first example, you can use the `observers.detach()` to remove observers.
462
+
463
+ But, there is an alternative method to remove observer objects or remove callables by their event names. The method to do this is: `observers.off()`.
464
+
465
+ ```ruby
466
+ class Order
467
+ include Micro::Observers
468
+ end
469
+
470
+ NotifyAfterCancel = -> {}
471
+
472
+ module OrderNotifications
473
+ def self.canceled(_order)
474
+ end
475
+ end
476
+
477
+ order = Order.new
478
+ order.observers.on(event: :canceled, call: NotifyAfterCancel)
479
+ order.observers.attach(OrderNotifications)
480
+
481
+ order.observers.some? # true
482
+ order.observers.count # 2
483
+
484
+ order.observers.off(:canceled) # removing the callable (NotifyAfterCancel).
485
+ order.observers.some? # true
486
+ order.observers.count # 1
487
+
488
+ order.observers.off(OrderNotifications)
489
+ order.observers.some? # false
490
+ order.observers.count # 0
491
+ ```
492
+
493
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
202
494
 
203
495
  ### ActiveRecord and ActiveModel integrations
204
496
 
205
- To make use of this feature you need to require an additional module (`require 'u-observers/for/active_record'`).
497
+ To make use of this feature you need to require an additional module.
206
498
 
207
499
  Gemfile example:
208
500
  ```ruby
@@ -211,16 +503,22 @@ gem 'u-observers', require: 'u-observers/for/active_record'
211
503
 
212
504
  This feature will expose modules that could be used to add macros (static methods) that were designed to work with `ActiveModel`/`ActiveRecord` callbacks. e.g:
213
505
 
214
-
215
506
  #### notify_observers_on()
216
507
 
217
- The `notify_observers_on` allows you to pass one or more `ActiveModel`/`ActiveRecord` callbacks, that will be used to notify your object observers.
508
+ The `notify_observers_on` allows you to define one or more `ActiveModel`/`ActiveRecord` callbacks, that will be used to notify your object observers.
218
509
 
219
510
  ```ruby
220
511
  class Post < ActiveRecord::Base
221
512
  include ::Micro::Observers::For::ActiveRecord
222
513
 
223
- notify_observers_on(:after_commit) # passing multiple callbacks. e.g. notify_observers_on(:before_save, :after_commit)
514
+ notify_observers_on(:after_commit) # using multiple callbacks. e.g. notify_observers_on(:before_save, :after_commit)
515
+
516
+ # The method above does the same as the commented example below.
517
+ #
518
+ # after_commit do |record|
519
+ # record.subject_changed!
520
+ # record.notify(:after_commit)
521
+ # end
224
522
  end
225
523
 
226
524
  module TitlePrinter
@@ -230,32 +528,39 @@ module TitlePrinter
230
528
  end
231
529
 
232
530
  module TitlePrinterWithContext
233
- def self.after_commit(post, context)
234
- puts "Title: #{post.title} (from: #{context[:from]})"
531
+ def self.after_commit(post, event)
532
+ puts "Title: #{post.title} (from: #{event.context[:from]})"
235
533
  end
236
534
  end
237
535
 
238
536
  Post.transaction do
239
537
  post = Post.new(title: 'Hello world')
240
- post.observers.attach(TitlePrinter, TitlePrinterWithContext, context: { from: 'example 4' })
538
+ post.observers.attach(TitlePrinter, TitlePrinterWithContext, context: { from: 'example #6' })
241
539
  post.save
242
540
  end
243
- # The message below will be printed by the observer (OrderEvents):
541
+ # The message below will be printed by the observers (TitlePrinter, TitlePrinterWithContext):
244
542
  # Title: Hello world
245
- # Title: Hello world (from: example 4)
543
+ # Title: Hello world (from: example #6)
246
544
  ```
247
545
 
248
- [⬆️ Back to Top](#table-of-contents-)
546
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
249
547
 
250
548
  #### notify_observers()
251
549
 
252
- The `notify_observers` allows you to pass one or more *events*, that will be used to notify after the execution of some `ActiveModel`/`ActiveRecord` callback.
550
+ The `notify_observers` allows you to define one or more *events*, that will be used to notify after the execution of some `ActiveModel`/`ActiveRecord` callback.
253
551
 
254
552
  ```ruby
255
553
  class Post < ActiveRecord::Base
256
554
  include ::Micro::Observers::For::ActiveRecord
257
555
 
258
556
  after_commit(&notify_observers(:transaction_completed))
557
+
558
+ # The method above does the same as the commented example below.
559
+ #
560
+ # after_commit do |record|
561
+ # record.subject_changed!
562
+ # record.notify(:transaction_completed)
563
+ # end
259
564
  end
260
565
 
261
566
  module TitlePrinter
@@ -265,24 +570,24 @@ module TitlePrinter
265
570
  end
266
571
 
267
572
  module TitlePrinterWithContext
268
- def self.transaction_completed(post, context)
269
- puts("Title: #{post.title} (from: #{context[:from]})")
573
+ def self.transaction_completed(post, event)
574
+ puts("Title: #{post.title} (from: #{event.ctx[:from]})")
270
575
  end
271
576
  end
272
577
 
273
578
  Post.transaction do
274
579
  post = Post.new(title: 'Olá mundo')
275
- post.observers.attach(TitlePrinter, TitlePrinterWithContext, context: { from: 'example 5' })
580
+ post.observers.attach(TitlePrinter, TitlePrinterWithContext, context: { from: 'example #7' })
276
581
  post.save
277
582
  end
278
- # The message below will be printed by the observer (OrderEvents):
583
+ # The message below will be printed by the observers (TitlePrinter, TitlePrinterWithContext):
279
584
  # Title: Olá mundo
280
- # Title: Olá mundo (from: example 5)
585
+ # Title: Olá mundo (from: example #5)
281
586
  ```
282
587
 
283
- PS: You can use `include ::Micro::Observers::For::ActiveModel` if your class only makes use of the `ActiveModel` and all the previous examples will work.
588
+ > **Note**: You can use `include ::Micro::Observers::For::ActiveModel` if your class only makes use of the `ActiveModel` and all the previous examples will work.
284
589
 
285
- [⬆️ Back to Top](#table-of-contents-)
590
+ [⬆️ &nbsp; Back to Top](#table-of-contents-)
286
591
 
287
592
  ## Development
288
593