Module: Micro::Observers::For::ActiveModel::ClassMethods

Defined in:
lib/micro/observers/for/active_model.rb

Instance Method Summary collapse

Instance Method Details

#__observers_to_notifyObject



122
123
124
# File 'lib/micro/observers/for/active_model.rb', line 122

def __observers_to_notify
  @__observers_to_notify ||= {}
end

#__observers_to_notify_callbacksObject



126
127
128
# File 'lib/micro/observers/for/active_model.rb', line 126

def __observers_to_notify_callbacks
  @__observers_to_notify_callbacks ||= {}
end

#detach_observers_to_notify(*observers, from: nil) ⇒ Object

Remove previously declared observers. Without ‘from:` they are removed from every callback; pass `from:` (a callback name or an array of them) to scope it. With no observers, clears the callback(s).



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/micro/observers/for/active_model.rb', line 59

def detach_observers_to_notify(*observers, from: nil)
  observers = Utils::Arrays.flatten_and_compact(observers)
  events = from ? Utils::Arrays.flatten_and_compact(from) : __observers_to_notify.keys

  events.each do |event|
    entries = __observers_to_notify[event]

    next unless entries

    if observers.empty?
      __observers_to_notify.delete(event)
    else
      entries.reject! { |observer, _context| observers.include?(observer) }
      __observers_to_notify.delete(event) if entries.empty?
    end
  end

  observers_to_notify
end

#install_observers_to_notify_callback(event, callback_options) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/micro/observers/for/active_model.rb', line 87

def install_observers_to_notify_callback(event, callback_options)
  installed = __observers_to_notify_callbacks

  return if installed[event]

  installed[event] = true

  declaring_class = self

  callback_block = proc do |record|
    declaring_class.send(:notify_registered_observers, record, event)
  end

  if callback_options.empty?
    self.public_send(event, &callback_block)
  else
    self.public_send(event, **callback_options, &callback_block)
  end
end

#notify_observers(*events) ⇒ Object



16
17
18
# File 'lib/micro/observers/for/active_model.rb', line 16

def notify_observers(*events)
  notify_observers_proc(Event::Names.fetch(events))
end

#notify_observers!(event:, with:, context: nil, **callback_options) ⇒ Object

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/micro/observers/for/active_model.rb', line 32

def notify_observers!(event:, with:, context: nil, **callback_options)
  observers = Utils::Arrays.flatten_and_compact(with)

  raise ArgumentError, NO_OBSERVERS_TO_NOTIFY_MSG if observers.empty?

  events = Utils::Arrays.flatten_and_compact(event)

  raise ArgumentError, NO_EVENT_TO_NOTIFY_MSG if events.empty?

  events.each do |callback_method|
    register_observers_to_notify(callback_method, observers, context)

    install_observers_to_notify_callback(callback_method, callback_options)
  end
end

#notify_observers_on(*callback_methods) ⇒ Object



20
21
22
23
24
# File 'lib/micro/observers/for/active_model.rb', line 20

def notify_observers_on(*callback_methods)
  Utils::Arrays.fetch_from_args(callback_methods).each do |callback_method|
    self.public_send(callback_method, &notify_observers_proc([callback_method]))
  end
end

#notify_observers_proc(events) ⇒ Object



9
10
11
12
13
14
# File 'lib/micro/observers/for/active_model.rb', line 9

def notify_observers_proc(events)
  proc do |object|
    object.observers.subject_changed!
    object.observers.send(:broadcast_if_subject_changed, events)
  end
end

#notify_registered_observers(record, event) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/micro/observers/for/active_model.rb', line 107

def notify_registered_observers(record, event)
  entries = __observers_to_notify[event]

  return if entries.nil? || entries.empty?

  set = record.observers

  entries.each do |observer, context|
    context ? set.attach(observer, context: context) : set.attach(observer)
  end

  set.subject_changed!
  set.send(:broadcast_if_subject_changed, [event])
end

#observers_to_notifyObject

Introspection: the observers declared via ‘notify_observers!`, keyed by the callback they fire on. e.g. { after_commit: [TitlePrinter] }



50
51
52
53
54
# File 'lib/micro/observers/for/active_model.rb', line 50

def observers_to_notify
  __observers_to_notify.each_with_object({}) do |(event, entries), result|
    result[event] = entries.map { |observer, _context| observer } unless entries.empty?
  end
end

#register_observers_to_notify(event, observers, context) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/micro/observers/for/active_model.rb', line 79

def register_observers_to_notify(event, observers, context)
  entries = (__observers_to_notify[event] ||= [])

  observers.each do |observer|
    entries << [observer, context] unless entries.any? { |existing, _| existing == observer }
  end
end