Skip to content

Handle events with private or protected methods

krisleech edited this page Nov 10, 2014 · 2 revisions

Wisper only allows listeners public methods to handle events. In some cases you might have a listener and would prefer the event handlers to be private methods. This might be the case is an object is both a publisher and listener. For a discussion around this please see this issue.

To allow protected and private methods to handle events a small hack is needed.

class ExposePrivateMethods
  def initialize(target)
    @target
  end

  def method_missing(method, *args, &block)
    if @target.respond_to?(method, include_all: true)
      @target.send(method, *args)
    else
      super
    end
  end

  def respond_to?(method)
    @target.respond_to?(method, include_all: true) || super
  end
end

Add a constructor method to the listener class to return a pre-wrapped listener, such as:

class MyListener
 def self.new_with_callbacks(*args)
   new(*args).with_callbacks
 end

  def with_callbacks
    ExposePrivateMethods.new(self)
  end
end

and subscribe:

my_publisher.subscribe(MyListener.new_with_callbacks)

A fuller example would be a service object which needs to call another service object and listen for its events.

class MyService
  def call
    # ...
    other_service = OtherService.new

    other_service.subscribe(self.with_callbacks)  
  end

  private

  # private, but is made publicly accessible by ExposePrivateMethods wrapper
  def on_other_service_successful
    # ...
  end

  def with_callbacks
    ExposePrivateMethods.new(self)
  end
end