module Hexx class Service # Wraps the service object and grants access to its private methods. # # @example # class GetItem < Hexx::Service # private # attr_reader :on_something, :something # end # # service = GetItem.new # service.respond_to? :on_something # => false # service.respond_to? :something # => false # # wrapper = Hexx::Service::WithCallbacks.new service, prefix: :on # wrapper.respond_to? :on_something # => true # wrapper.respond_to? :something # => false class WithCallbacks # @!scope class # @!method new(object, options) # Initializes the decorator of given object. # # @example (see Hexx::Service::WithCallbacks) # # @param [Hexx::Service] object The service object to be decorated. # @param [Hash] options The list of wrapper options. # @option options [Symbol] :prefix (nil) The prefix for private methods # to be accessible. # @api hide def initialize(object, prefix: nil) @object = object @prefix = Regexp.new(prefix ? "^#{ prefix }_" : "") end # @api hide # Redefines the +respond_to?+ to allow access to object's methods. # # @example # service = WithCallbacks(some_service, prefix: :on) # service.respond_to? :on_something # => true # # @param [Symbol] method The name of the method to check access to. def respond_to?(method, *) object.respond_to?(method) || valid_callback?(method) || super end # Compares the object with another service object. # The wrapper is equal to another wrapper for the same object and prefix. # # @example Wrappers are equal if they have the same objects and prefixes # service = Hexx::Service.new # a = Hexx::Service::WithCallbacks.new service, prefix: :on # b = Hexx::Service::WithCallbacks.new service, prefix: :on # a == b # => true # # @example Wrappers are different if they have different prefixes # service = Hexx::Service.new # a = Hexx::Service::WithCallbacks.new service, prefix: :on # b = Hexx::Service::WithCallbacks.new service, prefix: :when # a == b # => false # # @example Wrappers are different if they have different objects # a = Hexx::Service::WithCallbacks.new Hexx::Service.new, prefix: :on # b = Hexx::Service::WithCallbacks.new Hexx::Service.new, prefix: :on # a == b # => false # # @example A wrapper differs from any non-wrapper # service = Hexx::Service.new # a = Hexx::Service::WithCallbacks.new service, prefix: :on # a == service # => false # # @param [Object] other The other object to compare the wrapper to. # @return [Boolean]. def ==(other) return false unless other.is_a?(Service) || other.is_a?(self.class) value == other.value end protected # @api hide # The value to compare wrappers by. # @return [String] value. def value object.inspect + prefix.inspect end private # @api hide attr_reader :object, :prefix # @api hide def method_missing(method, *args, &block) valid_callback?(method) ? object.send(method, *args, &block) : super end # @api hide def valid_callback?(method) method.to_s[prefix] && object.respond_to?(method, include_all: true) end end end end