fattr 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,252 @@
1
+ NAME
2
+ fattr.rb
3
+
4
+ INSTALL
5
+ gem install fattrs
6
+
7
+ URIS
8
+ http://codeforpeople.com/lib/ruby
9
+ http://rubyforge.org/projects/codeforpeople/
10
+ http://codeforpeople.rubyforge.org/svn/
11
+
12
+ SYNOPSIS
13
+ fattr.rb is a "fatter attr" for ruby. fattr.rb supercedes attributes.rb as
14
+ that library, even though it added only one method to the global namespace,
15
+ collided too frequently with user code - in particular rails' code.
16
+
17
+ the implementation of fattr.rb borrows many of the best ideas from the
18
+ metakoans.rb ruby quiz
19
+
20
+ http://www.rubyquiz.com/quiz67.html
21
+
22
+ in particular the solutions of Christian Neukirchen and Florian Gross along
23
+ with concepts from the original traits.rb lib
24
+
25
+ key features provided by fattrs are
26
+
27
+ - ability to specify default values for attrs and definition time. values
28
+ can be literal objects or blocks, which are evaluated in the context of
29
+ self to initialize the variable
30
+
31
+ - classes remember which fattrs they've defined and this information is
32
+ available to client code
33
+
34
+ - a whole suite of methods is defined by calls to #fattrs including
35
+ getter, setter, query (var?) and banger (var! - which forces
36
+ re-initialization from the default value/block)
37
+
38
+ - ability to define multiple fattrs at once using key => value pairs
39
+
40
+ - fast lookup of whether or not a class has defined a certain fattr
41
+
42
+ - fattrs can be defined on objects on a per singleton basis
43
+
44
+ - getters acts as setters if an argument is given to them
45
+
46
+ - block caching, calling an fattr with a block sets the instance
47
+ variable to that block
48
+
49
+ all this in < 100 lines of code
50
+
51
+ HISTORY
52
+ 5.0.0:
53
+ port from attributes.rb retaining all the same features of that version of
54
+ attributes.rb
55
+
56
+ SAMPLES
57
+
58
+ <========< samples/a.rb >========>
59
+
60
+ ~ > cat samples/a.rb
61
+
62
+ #
63
+ # basic usage is like attr, but note that fattr defines a suite of methods
64
+ #
65
+ require 'fattr'
66
+
67
+ class C
68
+ fattr 'a'
69
+ end
70
+
71
+ c = C.new
72
+
73
+ c.a = 42
74
+ p c.a #=> 42
75
+ p 'forty-two' if c.a? #=> 'forty-two'
76
+
77
+ #
78
+ # fattrs works on object too
79
+ #
80
+ o = Object.new
81
+ o.fattr 'answer' => 42
82
+ p o.answer #=> 42
83
+
84
+ ~ > ruby samples/a.rb
85
+
86
+ 42
87
+ "forty-two"
88
+ 42
89
+
90
+
91
+ <========< samples/b.rb >========>
92
+
93
+ ~ > cat samples/b.rb
94
+
95
+ #
96
+ # default values may be given either directly or as a block which will be
97
+ # evaluated in the context of self. in both cases (value or block) the
98
+ # default is set only once and only if needed - it's a lazy evaluation. the
99
+ # 'banger' method can be used to re-initialize a variable at any point whether
100
+ # or not it's already been initialized.
101
+ #
102
+ require 'fattr'
103
+
104
+ class C
105
+ fattr :a => 42
106
+ fattr(:b){ Float a }
107
+ end
108
+
109
+ c = C.new
110
+ p c.a #=> 42
111
+ p c.b #=> 42.0
112
+
113
+ c.a = 43
114
+ p c.a #=> 43
115
+ c.a!
116
+ p c.a #=> 42
117
+
118
+ ~ > ruby samples/b.rb
119
+
120
+ 42
121
+ 42.0
122
+ 43
123
+ 42
124
+
125
+
126
+ <========< samples/c.rb >========>
127
+
128
+ ~ > cat samples/c.rb
129
+
130
+ #
131
+ # multiple values may by given, plain names and key/val pairs may be mixed.
132
+ #
133
+ require 'fattr'
134
+
135
+ class C
136
+ fattrs 'x', 'y' => 0b101000, 'z' => 0b10
137
+ end
138
+
139
+ c = C.new
140
+ c.x = c.y + c.z
141
+ p c.x #=> 42
142
+
143
+ ~ > ruby samples/c.rb
144
+
145
+ 42
146
+
147
+
148
+ <========< samples/d.rb >========>
149
+
150
+ ~ > cat samples/d.rb
151
+
152
+ #
153
+ # a nice feature is that all fattrs are enumerated in the class. this,
154
+ # combined with the fact that the getter method is defined so as to delegate
155
+ # to the setter when an argument is given, means bulk initialization and/or
156
+ # fattr traversal is very easy.
157
+ #
158
+ require 'fattr'
159
+
160
+ class C
161
+ fattrs %w( x y z )
162
+
163
+ def fattrs
164
+ self.class.fattrs
165
+ end
166
+
167
+ def initialize
168
+ fattrs.each_with_index{|a,i| send a, i}
169
+ end
170
+
171
+ def to_hash
172
+ fattrs.inject({}){|h,a| h.update a => send(a)}
173
+ end
174
+
175
+ def inspect
176
+ to_hash.inspect
177
+ end
178
+ end
179
+
180
+ c = C.new
181
+ p c.fattrs
182
+ p c
183
+
184
+ c.x 'forty-two'
185
+ p c.x
186
+
187
+ ~ > ruby samples/d.rb
188
+
189
+ ["x", "y", "z"]
190
+ {"x"=>0, "y"=>1, "z"=>2}
191
+ "forty-two"
192
+
193
+
194
+ <========< samples/e.rb >========>
195
+
196
+ ~ > cat samples/e.rb
197
+
198
+ #
199
+ # my favourite element of fattrs is that getters can also be setters.
200
+ # this allows incredibly clean looking code like
201
+ #
202
+ require 'fattr'
203
+
204
+ class Config
205
+ fattrs %w( host port)
206
+ def initialize(&block) instance_eval &block end
207
+ end
208
+
209
+ conf = Config.new{
210
+ host 'codeforpeople.org'
211
+
212
+ port 80
213
+ }
214
+
215
+ p conf
216
+
217
+ ~ > ruby samples/e.rb
218
+
219
+ #<Config:0x22ab0 @port=80, @host="codeforpeople.org">
220
+
221
+
222
+ <========< samples/f.rb >========>
223
+
224
+ ~ > cat samples/f.rb
225
+
226
+ #
227
+ # of course fattrs works as well at class/module level as at instance
228
+ # level
229
+ #
230
+ require 'fattr'
231
+
232
+ module Logging
233
+ Level_names = {
234
+ 0 => 'INFO',
235
+ # ...
236
+ 42 => 'DEBUG',
237
+ }
238
+
239
+ class << self
240
+ fattr 'level' => 42
241
+ fattr('level_name'){ Level_names[level] }
242
+ end
243
+ end
244
+
245
+ p Logging.level
246
+ p Logging.level_name
247
+
248
+ ~ > ruby samples/f.rb
249
+
250
+ 42
251
+ "DEBUG"
252
+
data/README.tmpl ADDED
@@ -0,0 +1,57 @@
1
+ NAME
2
+ fattr.rb
3
+
4
+ INSTALL
5
+ gem install fattrs
6
+
7
+ URIS
8
+ http://codeforpeople.com/lib/ruby
9
+ http://rubyforge.org/projects/codeforpeople/
10
+ http://codeforpeople.rubyforge.org/svn/
11
+
12
+ SYNOPSIS
13
+ fattr.rb is a "fatter attr" for ruby. fattr.rb supercedes attributes.rb as
14
+ that library, even though it added only one method to the global namespace,
15
+ collided too frequently with user code - in particular rails' code.
16
+
17
+ the implementation of fattr.rb borrows many of the best ideas from the
18
+ metakoans.rb ruby quiz
19
+
20
+ http://www.rubyquiz.com/quiz67.html
21
+
22
+ in particular the solutions of Christian Neukirchen and Florian Gross along
23
+ with concepts from the original traits.rb lib
24
+
25
+ key features provided by fattrs are
26
+
27
+ - ability to specify default values for attrs and definition time. values
28
+ can be literal objects or blocks, which are evaluated in the context of
29
+ self to initialize the variable
30
+
31
+ - classes remember which fattrs they've defined and this information is
32
+ available to client code
33
+
34
+ - a whole suite of methods is defined by calls to #fattrs including
35
+ getter, setter, query (var?) and banger (var! - which forces
36
+ re-initialization from the default value/block)
37
+
38
+ - ability to define multiple fattrs at once using key => value pairs
39
+
40
+ - fast lookup of whether or not a class has defined a certain fattr
41
+
42
+ - fattrs can be defined on objects on a per singleton basis
43
+
44
+ - getters acts as setters if an argument is given to them
45
+
46
+ - block caching, calling an fattr with a block sets the instance
47
+ variable to that block
48
+
49
+ all this in < 100 lines of code
50
+
51
+ HISTORY
52
+ 5.0.0:
53
+ port from attributes.rb retaining all the same features of that version of
54
+ attributes.rb
55
+
56
+ SAMPLES
57
+ @samples
data/gemspec.rb ADDED
@@ -0,0 +1,28 @@
1
+
2
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
3
+
4
+ require 'rubygems'
5
+
6
+ Gem::Specification::new do |spec|
7
+ $VERBOSE = nil
8
+ spec.name = lib
9
+ spec.version = version
10
+ spec.platform = Gem::Platform::RUBY
11
+ spec.summary = lib
12
+
13
+ spec.files = Dir::glob "**/**"
14
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
15
+
16
+ spec.require_path = "lib"
17
+ spec.autorequire = lib
18
+
19
+ spec.has_rdoc = File::exist? "doc"
20
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
21
+ #spec.add_dependency 'pervasives', '>= 1.0'
22
+
23
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
24
+
25
+ spec.author = "Ara T. Howard"
26
+ spec.email = "ara.t.howard@gmail.com"
27
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
28
+ end
data/gen_readme.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'pathname'
2
+
3
+ $VERBOSE=nil
4
+
5
+ def indent s, n = 2
6
+ ws = ' ' * n
7
+ s.gsub %r/^/, ws
8
+ end
9
+
10
+ template = IO::read 'README.tmpl'
11
+
12
+ samples = ''
13
+ prompt = '~ > '
14
+
15
+ Dir['sample*/*'] .each do |sample|
16
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
17
+
18
+ cmd = "cat #{ sample }"
19
+ samples << indent(prompt + cmd, 2) << "\n\n"
20
+ samples << indent(`#{ cmd }`, 4) << "\n"
21
+
22
+ cmd = "ruby #{ sample }"
23
+ samples << indent(prompt + cmd, 2) << "\n\n"
24
+
25
+ cmd = "ruby -Ilib #{ sample }"
26
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
27
+ end
28
+
29
+ #samples.gsub! %r/^/, ' '
30
+
31
+ readme = template.gsub %r/^\s*@samples\s*$/, samples
32
+ print readme
data/install.rb ADDED
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if (/\.svn/ =~ File.dirname(f))
40
+ next if f =~ %r/\.lnk/
41
+ next if f =~ %r/\.svn/
42
+ next if f =~ %r/\.swp/
43
+ next if f =~ %r/\.svn/
44
+ path.push f
45
+ dir |= [File.dirname(f)]
46
+ end
47
+ for f in dir
48
+ next if f == "."
49
+ next if f == "CVS"
50
+ File::makedirs(File.join(destdir, f))
51
+ end
52
+ for f in path
53
+ next if (/\~$/ =~ f)
54
+ next if (/^\./ =~ File.basename(f))
55
+ unless bin
56
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
57
+ else
58
+ from = File.join(srcdir, f)
59
+ to = File.join(destdir, f)
60
+ shebangify(from) do |sf|
61
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
62
+ $deferr.printf "chmod %04o %s\n", mode, to
63
+ File::install(sf, to, mode, false)
64
+ end
65
+ end
66
+ end
67
+ #}}}
68
+ end
69
+ def shebangify f
70
+ #{{{
71
+ open(f) do |fd|
72
+ buf = fd.read 42
73
+ if buf =~ %r/^\s*#\s*!.*ruby/o
74
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
75
+ begin
76
+ fd.rewind
77
+ ftmp.puts "#!#{ $ruby }"
78
+ while((buf = fd.read(8192)))
79
+ ftmp.write buf
80
+ end
81
+ ftmp.close
82
+ yield ftmp.path
83
+ ensure
84
+ ftmp.close!
85
+ end
86
+ else
87
+ yield f
88
+ end
89
+ end
90
+ #}}}
91
+ end
92
+ def ARGV.switch
93
+ #{{{
94
+ return nil if self.empty?
95
+ arg = self.shift
96
+ return nil if arg == '--'
97
+ if arg =~ /^-(.)(.*)/
98
+ return arg if $1 == '-'
99
+ raise 'unknown switch "-"' if $2.index('-')
100
+ self.unshift "-#{$2}" if $2.size > 0
101
+ "-#{$1}"
102
+ else
103
+ self.unshift arg
104
+ nil
105
+ end
106
+ #}}}
107
+ end
108
+ def ARGV.req_arg
109
+ #{{{
110
+ self.shift || raise('missing argument')
111
+ #}}}
112
+ end
113
+ def linkify d, linked = []
114
+ #--{{{
115
+ if test ?d, d
116
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
117
+ versioned.each do |v|
118
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
119
+ lnk = nil
120
+ begin
121
+ if test ?l, dst
122
+ lnk = "#{ dst }.lnk"
123
+ puts "#{ dst } -> #{ lnk }"
124
+ File::rename dst, lnk
125
+ end
126
+ unless test ?e, dst
127
+ puts "#{ src } -> #{ dst }"
128
+ File::copy src, dst
129
+ linked << dst
130
+ end
131
+ ensure
132
+ if lnk
133
+ at_exit do
134
+ puts "#{ lnk } -> #{ dst }"
135
+ File::rename lnk, dst
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ linked
142
+ #--}}}
143
+ end
144
+
145
+
146
+ #
147
+ # main program
148
+ #
149
+
150
+ libdir = $site_libdir
151
+ bindir = $bindir
152
+ no_linkify = false
153
+ linked = nil
154
+ help = false
155
+
156
+ usage = <<-usage
157
+ #{ File::basename $0 }
158
+ -d, --destdir <destdir>
159
+ -l, --libdir <libdir>
160
+ -b, --bindir <bindir>
161
+ -r, --ruby <ruby>
162
+ -n, --no_linkify
163
+ -s, --sudo
164
+ -h, --help
165
+ usage
166
+
167
+ begin
168
+ while switch = ARGV.switch
169
+ case switch
170
+ when '-d', '--destdir'
171
+ libdir = ARGV.req_arg
172
+ when '-l', '--libdir'
173
+ libdir = ARGV.req_arg
174
+ when '-b', '--bindir'
175
+ bindir = ARGV.req_arg
176
+ when '-r', '--ruby'
177
+ $ruby = ARGV.req_arg
178
+ when '-n', '--no_linkify'
179
+ no_linkify = true
180
+ when '-s', '--sudo'
181
+ sudo = 'sudo'
182
+ when '-h', '--help'
183
+ help = true
184
+ else
185
+ raise "unknown switch #{switch.dump}"
186
+ end
187
+ end
188
+ rescue
189
+ STDERR.puts $!.to_s
190
+ STDERR.puts usage
191
+ exit 1
192
+ end
193
+
194
+ if help
195
+ STDOUT.puts usage
196
+ exit
197
+ end
198
+
199
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
200
+
201
+ unless no_linkify
202
+ linked = linkify('lib') + linkify('bin')
203
+ end
204
+
205
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
206
+
207
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
208
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
209
+
210
+ if linked
211
+ linked.each{|path| File::rm_f path}
212
+ end
213
+
214
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/fattr.rb ADDED
@@ -0,0 +1,125 @@
1
+ module Fattr
2
+ Fattr::VERSION = '1.0.1' unless Fattr.const_defined?(:VERSION)
3
+ def self.version() Fattr::VERSION end
4
+
5
+ class List < ::Array
6
+ def << element
7
+ super
8
+ self
9
+ ensure
10
+ uniq!
11
+ index!
12
+ end
13
+
14
+ def index!
15
+ @index ||= Hash.new
16
+ each{|element| @index[element] = true}
17
+ end
18
+
19
+ def include? element
20
+ @index ||= Hash.new
21
+ @index[element] ? true : false
22
+ end
23
+
24
+ def initializers
25
+ @initializers ||= Hash.new
26
+ end
27
+ end
28
+
29
+ def fattrs *a, &b
30
+ unless a.empty?
31
+ returned = Hash.new
32
+
33
+ hashes, names = a.partition{|x| Hash === x}
34
+ names_and_defaults = {}
35
+ hashes.each{|h| names_and_defaults.update h}
36
+ names.flatten.compact.each{|name| names_and_defaults.update name => nil}
37
+
38
+ initializers = __fattrs__.initializers
39
+
40
+ names_and_defaults.each do |name, default|
41
+ raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
42
+ name = name.to_s
43
+
44
+ initialize = b || lambda { default }
45
+ initializer = lambda do |this|
46
+ Object.instance_method('instance_eval').bind(this).call &initialize
47
+ end
48
+ initializer_id = initializer.object_id
49
+ __fattrs__.initializers[name] = initializer
50
+
51
+ # setter, block invocation caches block
52
+ module_eval <<-code
53
+ def #{ name }=(*value, &block)
54
+ value.unshift block if block
55
+ @#{ name } = value.first
56
+ end
57
+ code
58
+
59
+ # getter, providing a value or block causes it to acts as setter
60
+ module_eval <<-code
61
+ def #{ name }(*value, &block)
62
+ value.unshift block if block
63
+ return self.send('#{ name }=', value.first) unless value.empty?
64
+ #{ name }! unless defined? @#{ name }
65
+ @#{ name }
66
+ end
67
+ code
68
+
69
+ # bang method re-calls any initializer given at declaration time
70
+ module_eval <<-code
71
+ def #{ name }!
72
+ initializer = ObjectSpace._id2ref #{ initializer_id }
73
+ self.#{ name } = initializer.call(self)
74
+ @#{ name }
75
+ end
76
+ code
77
+
78
+ # query simply defers to getter - cast to bool
79
+ module_eval <<-code
80
+ def #{ name }?
81
+ #{ name }
82
+ end
83
+ code
84
+
85
+ fattrs << name
86
+ returned[name] = initializer
87
+ end
88
+
89
+ returned
90
+ else
91
+ begin
92
+ __fattr_list__
93
+ rescue NameError
94
+ singleton_class =
95
+ class << self
96
+ self
97
+ end
98
+ klass = self
99
+ singleton_class.module_eval do
100
+ fattr_list = List.new
101
+ define_method('fattr_list'){ klass == self ? fattr_list : raise(NameError) }
102
+ alias_method '__fattr_list__', 'fattr_list'
103
+ end
104
+ __fattr_list__
105
+ end
106
+ end
107
+ end
108
+
109
+ %w( __fattrs__ __fattr__ fattr ).each{|dst| alias_method dst, 'fattrs'}
110
+ end
111
+
112
+ class Module
113
+ include Fattr
114
+ end
115
+
116
+ class Object
117
+ def fattrs *a, &b
118
+ sc =
119
+ class << self
120
+ self
121
+ end
122
+ sc.fattrs *a, &b
123
+ end
124
+ %w( __fattrs__ __fattr__ fattr ).each{|dst| alias_method dst, 'fattrs'}
125
+ end
data/samples/a.rb ADDED
@@ -0,0 +1,21 @@
1
+ #
2
+ # basic usage is like attr, but note that fattr defines a suite of methods
3
+ #
4
+ require 'fattr'
5
+
6
+ class C
7
+ fattr 'a'
8
+ end
9
+
10
+ c = C.new
11
+
12
+ c.a = 42
13
+ p c.a #=> 42
14
+ p 'forty-two' if c.a? #=> 'forty-two'
15
+
16
+ #
17
+ # fattrs works on object too
18
+ #
19
+ o = Object.new
20
+ o.fattr 'answer' => 42
21
+ p o.answer #=> 42
data/samples/b.rb ADDED
@@ -0,0 +1,22 @@
1
+ #
2
+ # default values may be given either directly or as a block which will be
3
+ # evaluated in the context of self. in both cases (value or block) the
4
+ # default is set only once and only if needed - it's a lazy evaluation. the
5
+ # 'banger' method can be used to re-initialize a variable at any point whether
6
+ # or not it's already been initialized.
7
+ #
8
+ require 'fattr'
9
+
10
+ class C
11
+ fattr :a => 42
12
+ fattr(:b){ Float a }
13
+ end
14
+
15
+ c = C.new
16
+ p c.a #=> 42
17
+ p c.b #=> 42.0
18
+
19
+ c.a = 43
20
+ p c.a #=> 43
21
+ c.a!
22
+ p c.a #=> 42
data/samples/c.rb ADDED
@@ -0,0 +1,12 @@
1
+ #
2
+ # multiple values may by given, plain names and key/val pairs may be mixed.
3
+ #
4
+ require 'fattr'
5
+
6
+ class C
7
+ fattrs 'x', 'y' => 0b101000, 'z' => 0b10
8
+ end
9
+
10
+ c = C.new
11
+ c.x = c.y + c.z
12
+ p c.x #=> 42
data/samples/d.rb ADDED
@@ -0,0 +1,34 @@
1
+ #
2
+ # a nice feature is that all fattrs are enumerated in the class. this,
3
+ # combined with the fact that the getter method is defined so as to delegate
4
+ # to the setter when an argument is given, means bulk initialization and/or
5
+ # fattr traversal is very easy.
6
+ #
7
+ require 'fattr'
8
+
9
+ class C
10
+ fattrs %w( x y z )
11
+
12
+ def fattrs
13
+ self.class.fattrs
14
+ end
15
+
16
+ def initialize
17
+ fattrs.each_with_index{|a,i| send a, i}
18
+ end
19
+
20
+ def to_hash
21
+ fattrs.inject({}){|h,a| h.update a => send(a)}
22
+ end
23
+
24
+ def inspect
25
+ to_hash.inspect
26
+ end
27
+ end
28
+
29
+ c = C.new
30
+ p c.fattrs
31
+ p c
32
+
33
+ c.x 'forty-two'
34
+ p c.x
data/samples/e.rb ADDED
@@ -0,0 +1,18 @@
1
+ #
2
+ # my favourite element of fattrs is that getters can also be setters.
3
+ # this allows incredibly clean looking code like
4
+ #
5
+ require 'fattr'
6
+
7
+ class Config
8
+ fattrs %w( host port)
9
+ def initialize(&block) instance_eval &block end
10
+ end
11
+
12
+ conf = Config.new{
13
+ host 'codeforpeople.org'
14
+
15
+ port 80
16
+ }
17
+
18
+ p conf
data/samples/f.rb ADDED
@@ -0,0 +1,21 @@
1
+ #
2
+ # of course fattrs works as well at class/module level as at instance
3
+ # level
4
+ #
5
+ require 'fattr'
6
+
7
+ module Logging
8
+ Level_names = {
9
+ 0 => 'INFO',
10
+ # ...
11
+ 42 => 'DEBUG',
12
+ }
13
+
14
+ class << self
15
+ fattr 'level' => 42
16
+ fattr('level_name'){ Level_names[level] }
17
+ end
18
+ end
19
+
20
+ p Logging.level
21
+ p Logging.level_name
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fattr
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard
8
+ autorequire: fattr
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-02-12 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: ara.t.howard@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - gemspec.rb
26
+ - gen_readme.rb
27
+ - install.rb
28
+ - lib
29
+ - lib/fattr.rb
30
+ - README
31
+ - README.tmpl
32
+ - samples
33
+ - samples/a.rb
34
+ - samples/b.rb
35
+ - samples/c.rb
36
+ - samples/d.rb
37
+ - samples/e.rb
38
+ - samples/f.rb
39
+ has_rdoc: false
40
+ homepage: http://codeforpeople.com/lib/ruby/fattr/
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.0.1
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: fattr
65
+ test_files: []
66
+