module Anise::Annotative::Methods

The Annotator::Method module allows for the creation of annotations which attach to the next method defined.

This idiom of annotation-before-definition was popularized by Rake’s ‘desc`/`task` pair. This module can be used to add similar capabilites to any class or module.

class X
  extend Anise::Annotative::Methods

  def self.doc(string)
    method_annotation(:doc => string)
  end

  doc "See what I mean?"

  def see
    puts "Yes, I see!"
  end
end

X.ann(:see, :doc) #=> "See what I mean?"

One can get a bit more control over the creation of annotations by using a block. In this case it is up the code to actually create the annotation.

def self.doc(string)
  method_annotation do |meth|
    ann meth, :doc => string
  end
end

Note that the library uses the method_added callback, so be sure to respect good practices of calling super if you need to override this method.

Public Class Methods

pending_annotations() click to toggle source

This a temporary store used to create method annotations.

# File lib/anise/annotative/methods.rb, line 51
def self.pending_annotations
  @_pending_annotations ||= Hash.new{ |h,k| h[k] = [] }
end

Public Instance Methods

annotator(name, &block) click to toggle source
Calls superclass method
# File lib/anise/annotative/methods.rb, line 76
def annotator(name, &block)
  if name.to_s.start_with?('@')
    if defined?(super)
      super(name, &block)
    else
      raise ArgumentError, "not a valid method name -- #{name}"
    end
  else
    method_annotator(name, &block)
  end
end
method_added(sym) click to toggle source

When a method is added, run all pending annotations.

@param [Symbol] sym

The name of the method added.
Calls superclass method
# File lib/anise/annotative/methods.rb, line 105
def method_added(sym)
  annotations = Methods.pending_annotations[self]
  annotations.each do |anns, block|
    if block
      block.call(sym)
    else
      anns.each do |name, value|
        if name.to_s.index('/')
          name, ns = name.to_s.split('/')
        else
          ns = :ann
        end
        ann(sym/ns, name=>value)
      end
    end
  end
  Methods.pending_annotations[self] = []
  super if defined?(super)
end
method_annotation(*args, &block) click to toggle source

Setup a pending method annotation.

@param [Hash] annotations

The annotation settings.
# File lib/anise/annotative/methods.rb, line 94
def method_annotation(*args, &block)
  anns = (Hash === args.last ? args.pop : {})
  Methods.pending_annotations[self] << [anns, block]
end
method_annotator(name, &block) click to toggle source

Define a method annotation.

@example

method_annotator :doc

@param name [Symbol]

Name of annotation.
# File lib/anise/annotative/methods.rb, line 64
def method_annotator(name, &block)
  (class << self; self; end).module_eval do
    define_method(name) do |*args|
      anns = { name => (args.size > 1 ? args : args.first) }
      Methods.pending_annotations[self] << [anns, block]
    end
  end
end