[ANN] fattr-2.0.0 (supporting class inheritable attributes)

A

ara.t.howard

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 Neukirchen 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

[ANN] fattr-1.0.2 5
[ANN] fattr-5.0.0 0
[ANN] attributes-3.3.0 0
[ANN] attributes-3.2.0 7
[ANN] attributes-4.1.0 0
[ANN] prototype-2.0.0 0
[ANN] attributes-4.0.0 0
ANN main-4.4.0 0

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top