u-observers 0.3.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fe383e800461aeb658a9b17f2d4799b194b7e70fdf5a545dbe07f69cd9d2642
4
- data.tar.gz: a42fdd9868c43855006b763faa86b0377ae2204f6e9c20893edfbadf49792a60
3
+ metadata.gz: 9b67e1c24feb02de944be44aacb6bba935d9dc1dfac6c53de2ba95dcffbd93ee
4
+ data.tar.gz: aead6fb10e5ada014fed52383f031d140363cbf4f7ef9b21f5ee7c9e9f54c792
5
5
  SHA512:
6
- metadata.gz: af8ce345aec2b28cef954f6de09ce835d1e4236e115877b04c92227121a85ebedd1b1cf422e3cc1645f2b7ad818cfdf81d9b05bcdb41007bca4fd9115d900fc0
7
- data.tar.gz: 45ade4eefd27ae3b8f0aed723681b5c1931cd11c34f78f17a21e59aa745a67de27b32272f4c01377950420f4dd0743c84258b9415cf24dea891d253f9ca1fe4b
6
+ metadata.gz: a77a575068bdee0f9312e25e5623a4031bb1369dee11df5d039121e84cf7cab418b8b37c3c93ff46265528304b64f80fc1be61ca42e78d9436e9e779c390b2bd
7
+ data.tar.gz: f90045332776294e6bc3bf6e70c34b0f24f40551f32a4d9be029ecd5fdfcad4b68d33b6f5c81802e9e257dedf9d1e16395bda434ee2dd48f38f9e291099a8a4e
@@ -2,23 +2,27 @@ require 'micro/observers/version'
2
2
 
3
3
  module Micro
4
4
  module Observers
5
+ require 'micro/observers/utils'
6
+ require 'micro/observers/events_or_actions'
5
7
  require 'micro/observers/manager'
6
8
 
7
9
  module ClassMethods
8
- def call_observers(with: :call)
9
- proc do |object|
10
- Array(with)
11
- .each { |action| object.observers.call(action) }
12
- end
10
+ def notify_observers!(with:)
11
+ proc { |object| with.each { |evt_or_act| object.observers.notify(evt_or_act) } }
13
12
  end
14
13
 
15
- def notify_observers(with: :call)
16
- call_observers(with: with)
14
+ def notify_observers(*events)
15
+ notify_observers!(with: EventsOrActions[events])
16
+ end
17
+
18
+ def call_observers(options = Utils::EMPTY_HASH)
19
+ notify_observers!(with: EventsOrActions.fetch_actions(options))
17
20
  end
18
21
  end
19
22
 
20
23
  def self.included(base)
21
24
  base.extend(ClassMethods)
25
+ base.send(:private_class_method, :notify_observers!)
22
26
  end
23
27
 
24
28
  def observers
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Observers
5
+
6
+ module EventsOrActions
7
+ DEFAULTS = [:call]
8
+
9
+ def self.[](value)
10
+ values = Utils.compact_array(value)
11
+
12
+ values.empty? ? DEFAULTS : values
13
+ end
14
+
15
+ def self.fetch_actions(hash)
16
+ return self[hash[:actions] || hash.fetch(:action)] if hash.is_a?(Hash)
17
+
18
+ raise ArgumentError, 'expected a hash with the key :action or :actions'
19
+ end
20
+
21
+ private_constant :DEFAULTS
22
+ end
23
+
24
+ end
25
+ end
@@ -4,9 +4,7 @@ module Micro
4
4
  module Observers
5
5
 
6
6
  class Manager
7
- EMPTY_HASH = {}.freeze
8
-
9
- SameObserver = -> (observer) do
7
+ EqualTo = -> (observer) do
10
8
  -> item { item[0] == :observer && item[1] == observer }
11
9
  end
12
10
 
@@ -17,56 +15,86 @@ module Micro
17
15
  def initialize(subject, list = nil)
18
16
  @subject = subject
19
17
 
20
- @list = (list.kind_of?(Array) ? list : []).flatten.tap(&:compact!)
18
+ @list = Utils.compact_array(list.kind_of?(Array) ? list : [])
21
19
  end
22
20
 
23
21
  def included?(observer)
24
- @list.any?(&SameObserver[observer])
22
+ @list.any?(&EqualTo[observer])
25
23
  end
26
24
 
27
- def attach(observer, options = EMPTY_HASH)
28
- if options[:allow_duplication] || !included?(observer)
29
- @list << [:observer, observer, options[:data]]
25
+ def attach(*args)
26
+ options = args.last.is_a?(Hash) ? args.pop : Utils::EMPTY_HASH
27
+
28
+ Utils.compact_array(args).each do |observer|
29
+ if options[:allow_duplication] || !included?(observer)
30
+ @list << [:observer, observer, options[:data]]
31
+ end
30
32
  end
31
33
 
32
34
  self
33
35
  end
34
36
 
35
- def on(options=EMPTY_HASH)
36
- action, callable, with = options[:action], options[:call], options[:with]
37
+ def on(options = Utils::EMPTY_HASH)
38
+ event, callable, with = options[:event], options[:call], options[:with]
37
39
 
38
- return self unless action.is_a?(Symbol) && callable.respond_to?(:call)
40
+ return self unless event.is_a?(Symbol) && callable.respond_to?(:call)
39
41
 
40
- arg = with.is_a?(Proc) ? with.call(@subject) : subject
42
+ @list << [:callable, event, [callable, with]]
43
+ end
44
+
45
+ def detach(*args)
46
+ Utils.compact_array(args).each do |observer|
47
+ @list.delete_if(&EqualTo[observer])
48
+ end
41
49
 
42
- @list << [:caller, action, [callable, arg]]
50
+ self
43
51
  end
44
52
 
45
- def detach(observer)
46
- @list.delete_if(&SameObserver[observer])
53
+ def notify(*events)
54
+ broadcast(EventsOrActions[events])
47
55
 
48
56
  self
49
57
  end
50
58
 
51
- def call(action = :call)
52
- @list.each do |type, observer, data|
53
- if type == :caller && observer == action
54
- data[0].call(data[1])
55
- elsif type == :observer && observer.respond_to?(action)
56
- handler = observer.method(action)
59
+ def call(options = Utils::EMPTY_HASH)
60
+ broadcast(EventsOrActions.fetch_actions(options))
57
61
 
58
- return handler.call(@subject) if handler.arity == 1
62
+ self
63
+ end
59
64
 
60
- handler.call(@subject, data)
65
+ private
66
+
67
+ def broadcast(evts_or_acts)
68
+ evts_or_acts.each do |evt_or_act|
69
+ @list.each do |strategy, observer, data|
70
+ call!(observer, strategy, data, with: evt_or_act)
71
+ end
61
72
  end
62
73
  end
63
74
 
64
- self
65
- end
75
+ def call!(observer, strategy, data, with:)
76
+ return call_callable(data) if strategy == :callable && observer == with
77
+
78
+ return call_observer(observer, with, data) if strategy == :observer
79
+ end
80
+
81
+ def call_callable(data)
82
+ callable, arg = data[0], data[1]
83
+
84
+ callable_arg = arg.is_a?(Proc) ? arg.call(@subject) : (arg || @subject)
66
85
 
67
- alias notify call
86
+ callable.call(callable_arg)
87
+ end
88
+
89
+ def call_observer(observer, method_name, data)
90
+ return unless observer.respond_to?(method_name)
91
+
92
+ handler = observer.method(method_name)
93
+
94
+ handler.arity == 1 ? handler.call(@subject) : handler.call(@subject, data)
95
+ end
68
96
 
69
- private_constant :EMPTY_HASH
97
+ private_constant :EqualTo
70
98
  end
71
99
 
72
100
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Observers
5
+
6
+ module Utils
7
+ EMPTY_HASH = {}.freeze
8
+
9
+ def self.compact_array(value)
10
+ Array(value).flatten.tap(&:compact!)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  module Micro
2
2
  module Observers
3
- VERSION = '0.3.0'
3
+ VERSION = '0.8.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-observers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-25 00:00:00.000000000 Z
11
+ date: 2020-09-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Simple and powerful implementation of the observer pattern.
14
14
  email:
@@ -27,7 +27,9 @@ files:
27
27
  - bin/console
28
28
  - bin/setup
29
29
  - lib/micro/observers.rb
30
+ - lib/micro/observers/events_or_actions.rb
30
31
  - lib/micro/observers/manager.rb
32
+ - lib/micro/observers/utils.rb
31
33
  - lib/micro/observers/version.rb
32
34
  - lib/u-observers.rb
33
35
  - u-observers.gemspec