In Files

Parent

Included Modules

Files

Protocol::ProtocolModule

A ProtocolModule object

Attributes

mode[R]

The current check mode :none, :warning, or :error (the default).

Public Class Methods

new(&block) click to toggle source

Creates an new ProtocolModule instance.

# File lib/protocol.rb, line 457
    def initialize(&block)
      @descriptor = Descriptor.new(self)
      @mode = :error
      module_eval(&block)
    end

Public Instance Methods

=~(object, mode = @mode) click to toggle source

Alias for check

[](name) click to toggle source

Return the Message object named name or nil, if it doesn’t exist.

# File lib/protocol.rb, line 533
    def [](name)
      name = name.to_s
      find { |m| m.name == name }
    end
check(object, mode = @mode) click to toggle source

Check the conformity of object recursively. This method returns either false OR true, if mode is :none or :warning, or raises an CheckFailed, if mode was :error.

# File lib/protocol.rb, line 587
    def check(object, mode = @mode)
      checked = {}
      result = true
      errors = CheckFailed.new
      each do |message|
        begin
          message.check(object, checked)
        rescue CheckError => e
          case mode
          when :error
            errors << e
          when :warning
            warn e.to_s
            result = false
          when :none
            result = false
          end
        end
      end
      raise errors unless errors.empty?
      result
    end
Also aliased as: =~
check_failure(mode) click to toggle source

Sets the check mode to id. id should be one of :none, :warning, or :error. The mode to use while doing a conformity check is always the root module, that is, the modes of the included modules aren’t important for the check.

# File lib/protocol.rb, line 639
    def check_failure(mode)
      CHECK_MODES.include?(mode) or
        raise ArgumentError, "illegal check mode #{mode}"
      @mode = mode
    end
check_failures(object) click to toggle source

Return all messages for whick a check failed.

# File lib/protocol.rb, line 613
    def check_failures(object)
      check object
    rescue CheckFailed => e
      return e.errors.map { |e| e.protocol_message }
    end
descriptors() click to toggle source

Returns all the protocol descriptions to check against as an Array.

# File lib/protocol.rb, line 467
    def descriptors
      descriptors = []
      protocols.each do |a|
        descriptors << a.instance_variable_get(:@descriptor)
      end
      descriptors
    end
each() click to toggle source

Alias for each_message

each_message() click to toggle source

Iterate over all messages and yield to all of them.

# File lib/protocol.rb, line 544
    def each_message(&block) # :yields: message
      messages.each(&block)
      self
    end
Also aliased as: each
grep(pattern) click to toggle source

Return all message whose names matches pattern.

# File lib/protocol.rb, line 539
    def grep(pattern)
      select { |m| pattern === m.name }
    end
implementation() click to toggle source

Switch to implementation mode. Defined methods are added to the ProtocolModule as instance methods.

# File lib/protocol.rb, line 693
    def implementation
      @implementation = true
    end
implementation?() click to toggle source

Return true, if the ProtocolModule is currently in implementation mode. Otherwise return false.

# File lib/protocol.rb, line 699
    def implementation?
      !!@implementation
    end
included(modul) click to toggle source

This callback is called, when a module, that was extended with Protocol, is included (via Modul#include/via Class#conform_to) into some other module/class. If modul is a Class, all protocol descriptions of the inheritance tree are collected and the given class is checked for conformance to the protocol. modul isn’t a Class and only a Module, it is extended with the Protocol module.

# File lib/protocol.rb, line 627
    def included(modul)
      super
      if modul.is_a? Class and @mode == :error or @mode == :warning
        $DEBUG and warn "#{name} is checking class #{modul}"
        check modul
      end
    end
inherit(modul, methodname, block_expected = nil) click to toggle source

Inherit a method signature from an instance method named methodname of modul. This means that this protocol should understand these instance methods with their arity and block expectation. Note that automatic detection of blocks does not work for Ruby methods defined in C. You can set the block_expected argument if you want to do this manually.

# File lib/protocol.rb, line 677
    def inherit(modul, methodname, block_expected = nil)
      Module === modul or
        raise TypeError, "expected Module not #{modul.class} as modul argument"
      methodnames = methodname.respond_to?(:to_ary) ?
        methodname.to_ary :
        [ methodname ]
      methodnames.each do |methodname|
        m = parse_instance_method_signature(modul, methodname)
        block_expected and m.block_expected = block_expected
        @descriptor.add_message m
      end
      self
    end
inspect() click to toggle source

Returns a short string representation of this protocol, that consists of the understood messages. This protocol

 FooProtocol = Protocol do
   def bar(x, y, &b) end
   def baz(x, y, z) end
   def foo(*rest) end
 end

returns this string:

 #<FooProtocol: bar(2&), baz(3), foo(-1)>
# File lib/protocol.rb, line 580
    def inspect
      "#<#{name}: #{messages.map { |m| m.shortcut } * ', '}>"
    end
messages() click to toggle source

Returns all messages this protocol (plus the included protocols) consists of in alphabetic order. This method caches the computed result array. You have to call reset_messages, if you want to recompute the array in the next call to messages.

# File lib/protocol.rb, line 501
    def messages
      result = []
      seen = {}
      descriptors.each do |d|
        dm = d.messages
        dm.delete_if do |m|
          delete = seen[m.name]
          seen[m.name] = true
          delete
        end
        result.concat dm
      end
      result.sort!
    end
Also aliased as: to_a
method_added(methodname) click to toggle source

Capture all added methods and either leave the implementation in place or add them to the protocol description.

# File lib/protocol.rb, line 717
    def method_added(methodname)
      methodname = methodname.to_s
      if specification? and methodname !~ /^__protocol_check_/
        protocol_check = instance_method(methodname)
        parser = MethodParser.new(self, methodname)
        if parser.complex?
          define_method("__protocol_check_#{methodname}", protocol_check)
          understand methodname, protocol_check.arity, parser.block_arg?
        else
          understand methodname, protocol_check.arity, parser.block_arg?
        end
        remove_method methodname
      else
        super
      end
    end
protocols() click to toggle source

Return self and all protocols included into self.

# File lib/protocol.rb, line 476
    def protocols
      ancestors.select { |modul| modul.is_a? ProtocolModule }
    end
reset_messages() click to toggle source

Reset the cached message array. Call this if you want to change the protocol dynamically after it was already used (= the messages method was called).

# File lib/protocol.rb, line 521
    def reset_messages
      @messages = nil
      self
    end
specification() click to toggle source

Switch to specification mode. Defined methods are added to the protocol description in order to be checked against in later conformance tests.

# File lib/protocol.rb, line 705
    def specification
      @implementation = false
    end
specification?() click to toggle source

Return true, if the ProtocolModule is currently in specification mode. Otherwise return false.

# File lib/protocol.rb, line 711
    def specification?
      !@implementation
    end
to_a() click to toggle source

Alias for messages

to_ruby(result = '') click to toggle source

Concatenates the protocol as Ruby code to the result string and return it. At the moment this method only supports method signatures with generic argument names.

# File lib/protocol.rb, line 483
    def to_ruby(result = '')
      result << "#{name} = Protocol do"
      first = true
      if messages.empty?
        result << "\n"
      else
        messages.each do |m|
          result << "\n"
          m.to_ruby(result)
        end
      end
      result << "end\n"
    end
to_s() click to toggle source

Returns a string representation of this protocol, that consists of the understood messages. This protocol

 FooProtocol = Protocol do
   def bar(x, y, &b) end
   def baz(x, y, z) end
   def foo(*rest) end
 end

returns this string:

 FooProtocol#bar(2&), FooProtocol#baz(3), FooProtocol#foo(-1)
# File lib/protocol.rb, line 564
    def to_s
      messages * ', '
    end
understand(methodname, arity = nil, block_expected = false) click to toggle source

This method defines one of the messages, the protocol in question consists of: The messages which the class, that conforms to this protocol, should understand and respond to. An example shows best which +message+descriptions_ are allowed:

 MyProtocol = Protocol do
   understand :bar            # conforming class must respond to :bar
   understand :baz, 3         # c. c. must respond to :baz with 3 args.
   understand :foo, -1        # c. c. must respond to :foo, any number of args.
   understand :quux, 0, true  # c. c. must respond to :quux, no args + block.
   understand :quux1, 1, true # c. c. must respond to :quux, 1 arg + block.
 end
# File lib/protocol.rb, line 657
    def understand(methodname, arity = nil, block_expected = false)
      m = Message.new(self, methodname.to_s, arity, block_expected)
      @descriptor.add_message(m)
      self
    end
understand?(name, arity = nil) click to toggle source

Returns true if it is required to understand the

# File lib/protocol.rb, line 527
    def understand?(name, arity = nil)
      name = name.to_s
      !!find { |m| m.name == name && (!arity || m.arity == arity) }
    end

Private Instance Methods

parse_instance_method_signature(modul, methodname) click to toggle source

(Not documented)

# File lib/protocol.rb, line 663
    def parse_instance_method_signature(modul, methodname)
      methodname = methodname.to_s
      method = modul.instance_method(methodname)
      real_module = Utilities.find_method_module(methodname, modul.ancestors)
      parser = MethodParser.new(real_module, methodname)
      Message.new(self, methodname, method.arity, parser.block_arg?)
    end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.