Module: Anise::Annotative::Methods

Includes:
Anise::Annotations
Defined in:
lib/anise/annotative/methods.rb

Overview

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.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Anise::Annotations

#ann, #ann!, #annotation_added, #annotations

Class Method Details

.pending_annotationsObject

This a temporary store used to create method annotations.



51
52
53
# File 'lib/anise/annotative/methods.rb', line 51

def self.pending_annotations
  @_pending_annotations ||= Hash.new{ |h,k| h[k] = [] }
end

Instance Method Details

#annotator(name, &block) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
# 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) ⇒ Object

When a method is added, run all pending annotations.

Parameters:

  • sym (Symbol)

    The name of the method added.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 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) ⇒ Object

Setup a pending method annotation.

Parameters:

  • annotations (Hash)

    The annotation settings.



94
95
96
97
# 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) ⇒ Object

Define a method annotation.

Examples:

method_annotator :doc

Parameters:

  • name (Symbol)

    Name of annotation.



64
65
66
67
68
69
70
71
# 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