Annotation

Annotations allows you to annontate objects, including methods with arbitrary "metadata". These annotations don’t do anything in themselves. They are merely comments. But you can put them to use. For instance an attribute validator might check for an annotation called :valid and test against it.

Annotation is an OpenObject, and is used across the board for keeping annotations.

Annotation class serves for both simple and inherited cases depending on whether a base class is given.

Synopsis

  class X
    attr :a
    ann :@a, :valid => lambda{ |x| x.is_a?(Integer) }

    def validate
      instance_variables.each { |iv|
        if validator = self.class.ann(iv)[:valid]
          value = instance_variable_get(iv)
          unless validator.call(vale)
            raise "Invalid value #{value} for #{iv}"
          end
        end
      }
    end

  end
Methods
Public Class methods
new( set={} )
# File lib/facets/more/annotation.rb, line 62
  def initialize( set={} )
    super( set )
  end
Public Instance methods
[](x)
# File lib/facets/more/annotation.rb, line 105
  def [](x)
    @base ? inheritance[x] : super
  end
inheritance()
# File lib/facets/more/annotation.rb, line 109
  def inheritance
    return self unless @base
    inh = @base.ancestors.collect{ |anc| @heritage.call(anc) }.compact
    if inh
      a = Annotation.new #( inh.pop.to_h )
      #inh.push( a ) #.dup )
      inh.reverse.inject(a){ |memo, i| memo.__merge__( i ) }
    end
  end
inherits( base, &heritage )
# File lib/facets/more/annotation.rb, line 66
  def inherits( base, &heritage )
    @base = base
    @heritage = heritage
    self
  end
method_missing( sym, *args, &blk )
# File lib/facets/more/annotation.rb, line 72
  def method_missing( sym, *args, &blk )
    name = sym.to_s.gsub(/([=!?])$/, '').to_sym
    type = sym.to_s[-1,1]

    unless @base
      r = super
      return Kernel.null if r.nil? and type != '?'
      return r
    else
      if type == '!'
        unless __key__?( name )
          parent = nil
          @base.ancestors.each do |anc|
            if ans = @heritage.call(anc) #anc.method_annotation[@key]
              if parent = ans[name]
                break
              end
            end
          end
          if parent
            return __table__[name] = parent.dup #vs. __class__.new?
          end
        end
        return super( name )
      end

      iob = dup
      super
      return inheritance if iob != self
      return inheritance.__send__( sym, *args, &blk )
    end
  end