fattr 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+