Skip to content

Commit

Permalink
Add Immutable Dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
dcsg committed Jul 14, 2017
1 parent 952730c commit b4d2aaf
Show file tree
Hide file tree
Showing 5 changed files with 413 additions and 2 deletions.
20 changes: 18 additions & 2 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2017-07-13 18:23:49 +0100 using RuboCop version 0.49.1.
# on 2017-07-14 08:36:02 +0100 using RuboCop version 0.49.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 4
# Offense count: 5
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
Max: 169

# Offense count: 1
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 11

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
# SupportedStyles: line_count_based, semantic, braces_for_chaining
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
# FunctionalMethods: let, let!, subject, watch
# IgnoredMethods: lambda, proc, it
Style/BlockDelimiters:
Exclude:
- 'lib/eventception/immutable_dispatcher.rb'

# Offense count: 2
# Cop supports --auto-correct.
Style/MutableConstant:
Expand Down
1 change: 1 addition & 0 deletions lib/eventception.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'eventception/event'
require 'eventception/listener_handler'
require 'eventception/dispatcher'
require 'eventception/immutable_dispatcher'
require 'eventception/base_subscriber'
require 'eventception/version'
54 changes: 54 additions & 0 deletions lib/eventception/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def listeners?

# Gets all listeners for the specific event sorted by descending priority.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# The event listeners for the specific event sorted by descending priority.
#
Expand All @@ -82,6 +86,10 @@ def listeners_for(event_name:)

# Checks whether are any registered listeners for the specific event.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# Boolean
#
Expand All @@ -96,16 +104,34 @@ def listeners_for?(event_name:)
# The event to listen on
# listener::
# The listener
# listener_method::
# The name of the method to be executed in the listener
# priority::
# The higher this value, the earlier an event listener will be triggered in the chain (defaults to 0)
#
# == Returns:
# Nil
#
def add_listener(event_name:, listener:, listener_method:, priority: 0)
event_listeners[event_name][priority] << ListenerHandler.new(listener, listener_method)
sorted.delete(event_name)

nil
end

# Removes an event listener from the specified events.
#
# == Parameters:
# event_name::
# The event to listen on
# listener::
# The listener
# listener_method::
# The name of the method to be executed in the listener
#
# == Returns:
# Nil
#
def remove_listener(event_name:, listener:, listener_method:)
return unless listeners_for?(event_name: event_name)

Expand All @@ -118,6 +144,8 @@ def remove_listener(event_name:, listener:, listener_method:)
end

event_listeners.delete(event_name) if listener_for_event.empty?

nil
end

# Add an event subscriber.
Expand All @@ -128,6 +156,9 @@ def remove_listener(event_name:, listener:, listener_method:)
# subscriber::
# The subscriber
#
# == Returns:
# Nil
#
def add_subscriber(subscriber:)
subscriber.subscribed_events.each do |event_subscribed|
add_listener(
Expand All @@ -137,8 +168,21 @@ def add_subscriber(subscriber:)
priority: event_subscribed[:priority] || 0,
)
end

nil
end

# Removes an event subscriber.
#
# The subscriber is asked for all the events he is interested in and added as a listener for these events.
#
# == Parameters:
# subscriber::
# The subscriber
#
# == Returns:
# Nil
#
def remove_subscriber(subscriber:)
subscriber.subscribed_events.each do |event_subscribed|
remove_listener(
Expand All @@ -147,6 +191,8 @@ def remove_subscriber(subscriber:)
listener_method: event_subscribed.fetch(:listener_method),
)
end

nil
end

protected
Expand All @@ -161,6 +207,9 @@ def remove_subscriber(subscriber:)
# event::
# The event
#
# == Returns:
# Nil
#
def do_dispatch(listeners:, event:)
listeners.each do |_priority, priority_listeners|
priority_listeners.each do |listener_handler|
Expand All @@ -181,8 +230,13 @@ def do_dispatch(listeners:, event:)
# event_name::
# The event name
#
# == Returns:
# Nil
#
def sort_listeners(event_name)
sorted[event_name] = event_listeners[event_name].sort_by { |key, _| -key }.to_h

nil
end
end
end
102 changes: 102 additions & 0 deletions lib/eventception/immutable_dispatcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# @author Daniel Gomes <danielcesargomes@gmail.com>
module Eventception
class ImmutableDispatcher
private

attr_reader :dispatcher

public

# Creates an unmodifiable proxy for an event dispatcher.
#
# == Parameters:
# listeners::
# Array of event listeners
# subscribers::
# Array of event subscribers
#
# == Returns:
# Nil
#
def initialize(listeners: [], subscribers: [])
@dispatcher = Eventception::Dispatcher.new

listeners.each do |listener|
dispatcher.add_listener(
event_name: listener.fetch(:event_name),
listener: listener.fetch(:listener),
listener_method: listener.fetch(:listener_method),
priority: listener.fetch(:priority, 0),
)
end

subscribers.each { |subscriber| dispatcher.add_subscriber(subscriber: subscriber) }

nil
end

# Dispatches an event to all registered listeners.
#
# == Parameters:
# event_name::
# The name of the event to dispatch. The name of
# the event is the name of the method that is
# invoked on listeners.
# event::
# The event to pass to the event handlers/listeners
# If not supplied, an empty Event instance is created.
#
# == Returns:
# The Event.
#
def dispatch(event_name:, event: Eventception::Event.new)
dispatcher.dispatch(event_name: event_name, event: event)

event
end

# Gets all listeners sorted by descending priority.
#
# == Returns:
# All event listeners sorted by event_name and descending priority.
#
def listeners
dispatcher.listeners
end

# Checks whether are any registered listeners.
#
# == Returns:
# Boolean
#
def listeners?
dispatcher.listeners?
end

# Gets all listeners for the specific event sorted by descending priority.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# The event listeners for the specific event sorted by descending priority.
#
def listeners_for(event_name:)
dispatcher.listeners_for(event_name: event_name)
end

# Checks whether are any registered listeners for the specific event.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# Boolean
#
def listeners_for?(event_name:)
dispatcher.listeners_for?(event_name: event_name)
end
end
end
Loading

0 comments on commit b4d2aaf

Please sign in to comment.