module Anise::Annotative::Attributes

The {Annotative::Attributes} mixin modifies the attr_* methods to allow easy addition of annotations for attributes. It modifies the built in attribute methods (attr, attr_reader, attr_writer and attr_accessor), and any other custom ‘attr_*` methods, to allow annotations to be added to them directly rather than requiring a separate annotating statement.

class X
  extend Anise::Annotative::Attributes

  attr :a, :valid => lambda{ |x| x.is_a?(Integer) }
end

See {Annotation} module for more information.

@todo Currently annotated attributes alwasy use the standard

annotator (:ann). In the future we might make this customizable.

Public Class Methods

define_annotated_attribute(base, attr_method_name) click to toggle source

Define an annotated attribute method, given an existing non-annotated attribute method.

Calls superclass method
# File lib/anise/annotative/attributes.rb, line 49
def self.define_annotated_attribute(base, attr_method_name)
  base.module_eval do
    define_method(attr_method_name) do |*args|
      args.flatten!

      harg={}; while args.last.is_a?(Hash)
        harg.update(args.pop)
      end

      raise ArgumentError if args.empty? and harg.empty?

      if args.empty?  # hash mode
        harg.each { |a,h| __send__(attr_method_name,a,h) }
      else
        klass = harg[:class] = args.pop if args.last.is_a?(Class)

        super(*args) #attr_method.call(*args)

        args.each{|a| ann(a.to_sym,harg)}

        instance_attributes!.concat(args)  #merge!

        # Use this callback to customize for your needs.
        if respond_to?(:attr_callback)
          attr_callback(self, args, harg)
        end

        # return the names of the attributes created
        return args
      end
    end
  end
end
extended(base) click to toggle source

When included into a class or module, {Annotation} is also included and {Attribute::Aid} extends the class/module.

@param base [Class, Module]

The class or module to get features.
# File lib/anise/annotative/attributes.rb, line 34
def self.extended(base)
  #inheritor :instance_attributes, [], :|
  base_class = (class << base; self; end)
  #base_class.attribute_methods.each do |attr_method|
  base.attribute_methods.each do |attr_method|
    define_annotated_attribute(base_class, attr_method)
  end
end

Public Instance Methods

attr(*args) click to toggle source

This defines a simple adjustment to attr to allow it to handle the boolean argument and to be able to accept attributes. It’s backward compatible and is not needed for Ruby 1.9 which gets rid of the secondary argument (or was suppose to!).

# File lib/anise/annotative/attributes.rb, line 127
def attr(*args)
  args.flatten!
  case args.last
  when TrueClass
    args.pop
    attr_accessor(*args)
  when FalseClass, NilClass
    args.pop
    attr_reader(*args)
  else
    attr_reader(*args)
  end
end
classified_attributes() click to toggle source

Return list of attributes that have a :class annotation.

class MyClass
  attr_accessor :test
  attr_accessor :name, String, :doc => 'Hello'
  attr_accessor :age, Fixnum
end

MyClass.instance_attributes # => [:test, :name, :age, :body]
MyClass.classified_attributes # => [:name, :age]
# File lib/anise/annotative/attributes.rb, line 116
def classified_attributes
  instance_attributes.find_all do |a|
    self.ann(a, :class)
  end
end
instance_attributes() click to toggle source

Instance attributes, including inherited attributes.

# File lib/anise/annotative/attributes.rb, line 86
def instance_attributes
  a = []
  ancestors.each do |anc|
    next unless anc < Attributes
    if x = anc.instance_attributes!
      a |= x
    end
  end
  return a
end
instance_attributes!() click to toggle source

Local instance attributes.

# File lib/anise/annotative/attributes.rb, line 100
def instance_attributes!
  @instance_attributes ||= []
end