Fattr-2.0.0 (supporting class inheritable attributes)

NAME
fattr.rb

INSTALL
gem install fattrs

URIS
http://github.com/ahoward/fattr
http://rubyforge.org/projects/codeforpeople/
http://codeforpeople.com/

SYNOPSIS
fattr.rb is a “fatter attr” for ruby

the implementation of fattr.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 N. and Florian
Gross along
with concepts from my original traits.rb lib

key features provided by fattrs 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 fattrs they've defined and this

information is
available to client code

- a whole suite of methods is defined by calls to #fattrs

including
getter, setter, query (var?) and banger (var! - which forces
re-initialization from the default value/block)

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

pairs

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

fattr

- fattrs can be defined on objects on a per singleton basis

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

- block caching, calling an fattr with a block sets the instance
  variable to that block

- shortcuts for adding class/module level fattrs

- class inheritable attributes

all this in 156 lines of code

SAMPLES

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

~ > cat samples/a.rb

#
# basic usage is like attr, but note that fattr defines a suite of

methods
#
require ‘fattr’

  class C
    fattr 'a'
  end

  c = C.new

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

#
# fattrs works on object too
#
  o = Object.new
  o.fattr '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 ‘fattr’

  class C
    fattr :a => 42
    fattr(: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 name=>default pairs can be given
#
  require 'fattr'

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

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

~ > ruby samples/c.rb

42

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

~ > cat samples/d.rb

#
# a nice feature is that all fattrs 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
# fattr traversal is very easy.
#
require ‘fattr’

  class C
    fattrs %w( x y z )

    def fattrs
      self.class.fattrs
    end

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

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

    def inspect
      to_hash.inspect
    end
  end

  c = C.new
  p c.fattrs
  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 fattrs is that getters can also be

setters.
# this allows incredibly clean looking code like
#
require ‘fattr’

  class Config
    fattrs %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:0x2cd1c @port=80, @host="codeforpeople.org">

<========< samples/f.rb >========>

~ > cat samples/f.rb

#
# of course fattrs works as well at class/module level as at

instance
# level
#
require ‘fattr’

  module Logging
    Level_names = {
      0 => 'INFO',
      # ...
      42 => 'DEBUG',
    }

    class << Logging
      fattr 'level' => 42
      fattr('level_name'){ Level_names[level] }
    end
  end

p Logging.level
p Logging.level_name

~ > ruby samples/f.rb

42
"DEBUG"

<========< samples/g.rb >========>

~ > cat samples/g.rb

#
# you can add class/module fattrs the 'normal' way or using the

provided
# shortcut method
#
require ‘fattr’

  class C
    class << C
      fattr 'a' => 4
    end

    Fattr 'b' => 2
  end

  p [ C.a, C.b ].join

~ > ruby samples/g.rb

"42"

<========< samples/h.rb >========>

~ > cat samples/h.rb

#
# class variable inheritance is supported simply
#
  require 'fattr'

  class A
    Fattr :x, :default => 42, :inheritable => true
  end

  class B < A
  end

  class C < B
  end

  p C.x #=> 42

  A.x = 42.0
  B.x = 'forty-two'

  p A.x #=> 42.0
  p B.x #=> 'forty-two'
  p C.x #=> 42

  C.x! # re-initialize from closest ancestor (B)

  p A.x #=> 42.0
  p B.x #=> 'forty-two'
  p C.x #=> 'forty-two'

~ > ruby samples/h.rb

42
42.0
"forty-two"
42
42.0
"forty-two"
"forty-two"

HISTORY
2.0.0:
support class/module inheritable attributes

1.1.0:
ruby19 testing. move to github.

1.0.2:
added Fattr shortcut for adding class/module level fattrs

  class C
    Fattr 'children' => []

    def C.inherited other
      (children << other).uniq!
      super
    end
  end

  class B < C
  end

  p C.children #=> B

1.0.0:
port from attributes.rb retaining all the same features of that
version of
attributes.rb

enjoy.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs