# Fattr-1.0.2

**URL:** <https://www.ruby-forum.com/t/fattr-1-0-2/131327>\
**Category:** Ruby\
**Created:** [March 8, 2008, 5:09am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327 "2008-03-08T05:09:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 8, 2008, 5:09am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/1 "2008-03-08T05:09:33Z")

</div>

NAME  
fattr.rb

INSTALL  
gem install fattrs

URIS  
[http://codeforpeople.com/lib/ruby](http://codeforpeople.com/lib/ruby)  
[http://rubyforge.org/projects/codeforpeople/](http://rubyforge.org/projects/codeforpeople/)  
[http://codeforpeople.rubyforge.org/svn/](http://codeforpeople.rubyforge.org/svn/)

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

fattr.rb supercedes attributes.rb as that library, even though it  
added only  
one method to the global namespace, collided too frequently with  
user code -  
in particular rails’ code.

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 the 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

```

all this in \< 100 lines of code

HISTORY  
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

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 values may by given, plain names and key/val pairs may

```

be mixed.  
#  
require ‘fattr’

```
   class C
     fattrs '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 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:0x224d4 @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 << self
       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 << self
       fattr 'a' => 4
     end

     Fattr 'b' => 2
   end

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

```

~ \> ruby samples/g.rb

```
 "42"

```

enjoy!

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 8, 2008, 5:19am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/2 "2008-03-08T05:19:30Z")

</div>

On Mar 7, 9:08 pm, ara howard [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> the  
> - ability to specify default values for attrs and definition  
> getter, setter, query (var?) and banger (var! - which forces
> 
> ```
> - block caching, calling an fattr with a block sets the instance
> variable to that block
> 
> - shortcuts for adding class/module level fattrs
> 
> ```

Interesting. What about data types?

class C  
fattr ‘a’ =\> Integer  
end

c = C.new  
c.a = 42 # ok  
c.a = ‘hello’ # TypeError

You may have this, but I didn’t see it in the samples or readme (but  
very well may have missed it).

Regards,

Dan

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 8, 2008, 6:57am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/3 "2008-03-08T06:57:18Z")

</div>

On Mar 7, 2008, at 9:18 PM, Daniel B. wrote:

> You may have this, but I didn’t see it in the samples or readme (but  
> very well may have missed it).

it is _far_ more heavyweight, but see

[http://codeforpeople.com/lib/ruby/traits/traits-0.9.2/README](http://codeforpeople.com/lib/ruby/traits/traits-0.9.2/README)

it also supports aspects, validation, and a ton of other stuff

cheers.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 8, 2008, 7:14am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/4 "2008-03-08T07:14:17Z")

</div>

From: ara howard [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

# it is _far_ more heavyweight, but see

if it isn’t slow, i’d prefer it over fattr any time. mixing the two  
seems to make my head shake a little 🙂 in fact, i would have even  
alias fattr to traits :))

thanks for traits, btw. it is cool

kind regards -botp

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 8, 2008, 7:38am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/5 "2008-03-08T07:38:17Z")

</div>

On Mar 7, 2008, at 11:13 PM, Peña, Botp wrote:

> # it is _far_ more heavyweight, but see
> 
> if it isn’t slow, i’d prefer it over fattr any time. mixing the two  
> seems to make my head shake a little 🙂 in fact, i would have even  
> alias fattr to traits :))
> 
> thanks for traits, btw. it is cool

heh - yeah traits is powerful and robust, but the code makes _my_ head  
spin. i’d like to rewrite in the style of fattr - but supporting all  
the same features - not time attm tho…

cheers.

a @ [http://drawohara.com/](http://drawohara.com/)

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 9, 2008, 12:19am UTC](https://www.ruby-forum.com/t/fattr-1-0-2/131327/6 "2008-03-09T00:19:01Z")

</div>

You might also be interested in doodle ([http://doodle.rubyforge.org](http://doodle.rubyforge.org))  
which I’ve just released.

$ xmpfilter examples/foo.rb  
require ‘rubygems’  
require ‘doodle’

class Foo \< Doodle::Base  
has :name, :kind =\> String  
end

foo = Foo “Bar”  
foo # =\> #\<Foo:0x10a1378 @name=“Bar”\>  
baz = Foo 1

# ~\> -:10: name must be String - got Fixnum(1) (Doodle::ValidationError)

Regards,  
Sean
