Class: PgEventstore::Callbacks

Inherits:
Object
  • Object
show all
Defined in:
lib/pg_eventstore/callbacks.rb,
sig/pg_eventstore/callbacks.rbs

Overview

Allows you to define before, around and after callbacks withing the certain action. It is especially useful during asynchronous programming when you need to be able to react on asynchronous actions from the outside. Example:

class MyAwesomeClass
attr_reader :callbacks

def initialize
  @callbacks = PgEventstore::Callbacks.new
end

def do_something
  Thread.new do
    @callbacks.run_callbacks(:something_happened) do
      puts "I did something useful!"
    end
  end
end

def do_something_else
  @callbacks.run_callbacks(:something_else_happened, :foo, bar: :baz) do
    puts "Something else happened!"
  end
end
end

obj = MyAwesomeClass.new
obj.callbacks.define_callback(:something_happened, :before, proc { puts "In before callback" })
obj.callbacks.define_callback(:something_happened, :after, proc { puts "In after callback" })
obj.callbacks.define_callback(
:something_happened, :around,
proc { |action| puts "In around before action"; action.call; puts "In around after action" }
)
obj.do_something

Outputs:

In before callback
In around callback before action
I did something useful!
In around callback after action
In after callback

Please note, that it is important to call action.call in around callback. Otherwise action simply won't be called.

Optionally you can provide any set of arguments to #run_callbacks method. They will be passed to your callbacks functions then. Example:

obj = MyAwesomeClass.new
obj.callbacks.define_callback(
:something_else_happened, :before,
proc { |*args, **kwargs| puts "In before callback. Args: #{args}, kwargs: #{kwargs}." }
)
obj.callbacks.define_callback(
:something_else_happened, :after,
proc { |*args, **kwargs| puts "In after callback. Args: #{args}, kwargs: #{kwargs}." }
)
obj.callbacks.define_callback(
:something_else_happened, :around,
proc { |action, *args, **kwargs|
  puts "In around before action. Args: #{args}, kwargs: #{kwargs}."
  action.call
  puts "In around after action. Args: #{args}, kwargs: #{kwargs}."
}
)
obj.do_something_else

Outputs:

In before callback. Args: [:foo], kwargs: {:bar=>:baz}.
In around before action. Args: [:foo], kwargs: {:bar=>:baz}.
I did something useful!
In around after action. Args: [:foo], kwargs: {:bar=>:baz}.
In after callback. Args: [:foo], kwargs: {:bar=>:baz}.

Instance Method Summary collapse

Constructor Details

#initializeCallbacks

Returns a new instance of Callbacks.



73
74
75
# File 'lib/pg_eventstore/callbacks.rb', line 73

def initialize
  @callbacks = {}
end

Instance Method Details

#clearvoid

This method returns an undefined value.

Clear all defined callbacks



112
113
114
# File 'lib/pg_eventstore/callbacks.rb', line 112

def clear
  @callbacks.clear
end

#define_callback(action, filter, callback) ⇒ void

This method returns an undefined value.

@param action — an object, that represents your action. In most cases you want to use a symbol there

@param filter — callback filter. Supported values are :before, :after and :around

@param callback

Parameters:

  • action (Object)
  • filter (Symbol)
  • callback (_Callback)


81
82
83
84
85
# File 'lib/pg_eventstore/callbacks.rb', line 81

def define_callback(action, filter, callback)
  @callbacks[action] ||= {}
  @callbacks[action][filter] ||= []
  @callbacks[action][filter].push(callback)
end

#remove_callback(action, filter, callback) ⇒ void

This method returns an undefined value.

Parameters:

  • action (Object)
  • filter (Symbol)
  • callback (#call)


104
105
106
107
108
# File 'lib/pg_eventstore/callbacks.rb', line 104

def remove_callback(action, filter, callback)
  return unless @callbacks.dig(action, filter)

  @callbacks[action][filter].delete(callback)
end

#run_after_callbacks(action, *args, **kwargs) ⇒ void

This method returns an undefined value.

Parameters:

  • action (Object)
  • args (Object)
  • kwargs (Object)


142
143
144
145
146
# File 'lib/pg_eventstore/callbacks.rb', line 142

def run_after_callbacks(action, *args, **kwargs)
  @callbacks[action][:after]&.each do |callback|
    callback.call(*args, **kwargs)
  end
end

#run_around_callbacks(action, *args, **kwargs) ⇒ Object

Returns the result of the passed block.

Parameters:

  • action (Object)
  • args (Object)
  • kwargs (Object)

Returns:

  • (Object)

    the result of the passed block



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/pg_eventstore/callbacks.rb', line 126

def run_around_callbacks(action, *args, **kwargs, &)
  result = nil
  stack = [proc { result = yield if block_given? }]
  @callbacks[action][:around]&.reverse_each&.with_index do |callback, index|
    stack.push(
      proc {
        callback.call(stack[index], *args, **kwargs)
        result
      }
    )
  end
  stack.last.call(*args, **kwargs)
  result
end

#run_before_callbacks(action, *args, **kwargs) ⇒ void

This method returns an undefined value.

Parameters:

  • action (Object)
  • args (Object)
  • kwargs (Object)


119
120
121
122
123
# File 'lib/pg_eventstore/callbacks.rb', line 119

def run_before_callbacks(action, *args, **kwargs)
  @callbacks[action][:before]&.each do |callback|
    callback.call(*args, **kwargs)
  end
end

#run_callbacks(action) ⇒ void

This method returns an undefined value.

@param action — an action to run

Parameters:

  • action (Object)
  • args (Object)
  • kwargs (Object)


90
91
92
93
94
95
96
97
# File 'lib/pg_eventstore/callbacks.rb', line 90

def run_callbacks(action, *, **, &)
  return (yield if block_given?) unless @callbacks[action]

  run_before_callbacks(action, *, **)
  result = run_around_callbacks(action, *, **, &)
  run_after_callbacks(action, *, **)
  result
end