[ANN] attributes-4.0.0

NAME
   attributes.rb

INSTALL
   gem install attributes

URIS
   http://rubyforge.org/projects/codeforpeople/
   http://codeforpeople.com/lib/ruby

SYNOPSIS
   attributes.rb provides a set of attr_* like method with several user
   friendly additions. attributes.rb is similar to the traits.rb package but
   sacrifices a few features for simplicity of implementation.

   the implementation of attributes.rb borrows many of the best ideas from the
   metakoans.rb ruby quiz

     http://www.rubyquiz.com/quiz67.html

   in particular the solutions of Christian Neukirchen and Florian Gross along
   with concepts from the original traits lib

   key features provided by attributes are

     - ability to specify default values for attrs and definition time. values
       can be literal objects or blocks, which are evaluated in the context of
       self to initialize the variable

     - classes remember which attributes they've defined and this information is
      available to client code

     - a whole suite of methods is defined by calls to #attributes including
      getter, setter, query (var?) and banger (var! - which forces
      re-initialization from the default value)

     - ability to define multiple attributes at once using key => value pairs

     - fast lookup of whether or not a class has defined a certain attribute

     - attributes can be defined on objects on a per singleton basis as well

     - getters acts as setters if an argument is given to them

   all this in < 100 lines of code

HISTORY
   4.0.0
     - removed dependancy on, and bundle of, pervasives
     - faster. as fast as normal method definition.
     - faster lookup for MyClass.attributes.include?('foobar')

   3.7.0
     small patch to use 'instance_variable_defined?' instead of defined?
     keyword

   3.5.0
     migrated to a pervasives based impl to attributes should work on any
     object - even blankslate objects

   3.3.0

     moved to an instance variable-less model using an module level closure for
     the attributes list

SAMPLES

   <========< samples/a.rb >========>

   ~ > cat samples/a.rb

···

#
     # basic usage is like attr, but note that attribute defines a suite of methods
     #
       require 'attributes'

       class C
         attribute 'a'
       end

       c = C.new

       c.a = 42
       p c.a #=> 42
       p 'forty-two' if c.a? #=> 'forty-two'

     #
     # attributes works on object too
     #
       o = Object.new
       o.attribute 'answer' => 42
       p o.answer #=> 42

   ~ > ruby samples/a.rb

     42
     "forty-two"
     42

   <========< samples/b.rb >========>

   ~ > cat samples/b.rb

     #
     # default values may be given either directly or as a block which will be
     # evaluated in the context of self. in both cases (value or block) the
     # default is set only once and only if needed - it's a lazy evaluation. the
     # 'banger' method can be used to re-initialize a variable at any point whether
     # or not it's already been initialized.
     #
       require 'attributes'

       class C
         attribute :a => 42
         attribute(:b){ Float a }
       end

       c = C.new
       p c.a #=> 42
       p c.b #=> 42.0

       c.a = 43
       p c.a #=> 43
       c.a!
       p c.a #=> 42

   ~ > ruby samples/b.rb

     42
     42.0
     43
     42

   <========< samples/c.rb >========>

   ~ > cat samples/c.rb

     #
     # multiple values may by given, plain names and key/val pairs may be mixed.
     #
       require 'attributes'

       class C
         attributes 'x', 'y' => 0b101000, 'z' => 0b10
       end

       c = C.new
       c.x = c.y + c.z
       p c.x #=> 42

   ~ > ruby samples/c.rb

     42

   <========< samples/d.rb >========>

   ~ > cat samples/d.rb

     #
     # a nice feature is that all attributes are enumerated in the class. this,
     # combined with the fact that the getter method is defined so as to delegate
     # to the setter when an argument is given, means bulk initialization and/or
     # attribute traversal is very easy.
     #
       require 'attributes'

       class C
         attributes %w( x y z )

         def attributes
           self.class.attributes
         end

         def initialize
           attributes.each_with_index{|a,i| send a, i}
         end

         def to_hash
           attributes.inject({}){|h,a| h.update a => send(a)}
         end

         def inspect
           to_hash.inspect
         end
       end

       c = C.new
       p c.attributes
       p c

       c.x 'forty-two'
       p c.x

   ~ > ruby samples/d.rb

     ["x", "y", "z"]
     {"x"=>0, "y"=>1, "z"=>2}
     "forty-two"

   <========< samples/e.rb >========>

   ~ > cat samples/e.rb

     #
     # my favourite element of attributes is that getters can also be setters.
     # this allows incredibly clean looking code like
     #
       require 'attributes'

       class Config
         attributes %w( host port)
         def initialize(&block) instance_eval &block end
       end

       conf = Config.new{
         host 'codeforpeople.org'

         port 80
       }

       p conf

   ~ > ruby samples/e.rb

     #<Config:0x20080 @port=80, @host="codeforpeople.org">

enjoy.

a @ http://codeforpeople.com/
--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama