Sha256: 63f919f13f9abe207cc9e7439b1dda3b107ceee82d72c75cf18ef35c437ee3ed

Contents?: true

Size: 1.92 KB

Versions: 7

Compression:

Stored size: 1.92 KB

Contents

module Surrounded
  module Context
    class Negotiator
      class << self
        # Return a class which has methods defined to forward the method to
        # the wrapped object delegating to the behavior module.
        # This prevents hits to method_missing.
        def for_role(mod)
          klass = Class.new(self)
          # Define access to the provided module
          klass.send(:define_method, :__behaviors__) do
            mod
          end
          # For each method in the module, directly forward to the wrapped object to
          # circumvent method_missing
          mod.instance_methods(false).each do |meth|
            num = __LINE__; klass.class_eval %{
              def #{meth}(*args, &block)
                __behaviors__.instance_method(:#{meth}).bind(@object).call(*args, &block)
              end
            }, __FILE__, num
          end
          klass
        end
      end


      identity = %w[__send__ object_id equal?]
      method_access = %w[respond_to? method __behaviors__]

      reserved_methods = (identity + method_access).join('|')

      # Remove all methods except the reserved methods
      instance_methods.reject{ |m|
        m.to_s =~ /#{reserved_methods}/
      }.each do |meth|
        undef_method meth
      end

      include Surrounded

      private

      # Store the context in the wrapped object if it can do so
      def store_context(&block)
        if @object.respond_to?(__method__, true)
          @object.send(__method__, &block)
        else
          super
        end
        self
      end
      # These only differ in the message they send
      alias remove_context store_context

      def initialize(object)
        @object = object
      end

      def method_missing(meth, *args, &block)
        @object.send(meth, *args, &block)
      end

      def respond_to_missing?(meth, include_private=false)
        @object.respond_to?(meth, include_private)
      end
    end
  end
end

Version data entries

7 entries across 7 versions & 1 rubygems

Version Path
surrounded-1.0.0 lib/surrounded/context/negotiator.rb
surrounded-0.9.11 lib/surrounded/context/negotiator.rb
surrounded-0.9.10 lib/surrounded/context/negotiator.rb
surrounded-0.9.9 lib/surrounded/context/negotiator.rb
surrounded-0.9.8 lib/surrounded/context/negotiator.rb
surrounded-0.9.7 lib/surrounded/context/negotiator.rb
surrounded-0.9.6 lib/surrounded/context/negotiator.rb