Sha256: f8a0c44241e0935bbbdb60f8647ec4062bdd3e031c3e3e324d5cd5f4550ca731

Contents?: true

Size: 1.62 KB

Versions: 1

Compression:

Stored size: 1.62 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)
          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.send(:define_method, :__behaviors__) do
            mod
          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 identity methods
      instance_methods.reject{ |m|
        m.to_s =~ /#{reserved_methods}/
      }.each do |meth|
        undef_method meth
      end

      private

      def initialize(object)
        @object, @behaviors = object, __behaviors__
      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

    # The method_missing definition from Surrounded will apply
    # before the one defined above. This allows the methods for
    # the objects in the context to work properly
    Negotiator.send(:prepend, Surrounded)
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
surrounded-0.9.5 lib/surrounded/context/negotiator.rb