# Fattr-2.0.0 (supporting class inheritable attributes)

**URL:** <https://www.ruby-forum.com/t/fattr-2-0-0-supporting-class-inheritable-attributes/177128>\
**Category:** Ruby\
**Created:** [October 12, 2009, 6:00am UTC](https://www.ruby-forum.com/t/fattr-2-0-0-supporting-class-inheritable-attributes/177128 "2009-10-12T06:00:14Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![ahoward](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/779978/32.png) [@ahoward](https://www.ruby-forum.com/u/ahoward)\
**Post date:** [October 12, 2009, 6:00am UTC](https://www.ruby-forum.com/t/fattr-2-0-0-supporting-class-inheritable-attributes/177128/1 "2009-10-12T06:00:14Z")

</div>

NAME  
fattr.rb

INSTALL  
gem install fattrs

URIS  
[GitHub - ahoward/fattr: fattr.rb is a "fatter attr" for ruby and borrows heavily from the metakoans.rb ruby quiz](http://github.com/ahoward/fattr)  
[http://rubyforge.org/projects/codeforpeople/](http://rubyforge.org/projects/codeforpeople/)  
[http://codeforpeople.com/](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.
