attributes1 5.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,331 @@
1
+ NAME
2
+ attributes.rb
3
+
4
+ INSTALL
5
+ gem install attributes
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
+ attributes.rb provides a set of attr_* like method with several user
14
+ friendly additions. attributes.rb is similar to the traits.rb package but
15
+ sacrifices a few features for simplicity of implementation.
16
+
17
+ the implementation of attributes.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 lib
24
+
25
+ key features provided by attributes 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 attributes they've defined and this information is
32
+ available to client code
33
+
34
+ - a whole suite of methods is defined by calls to #attributes including
35
+ getter, setter, query (var?) and banger (var! - which forces
36
+ re-initialization from the default value)
37
+
38
+ - ability to define multiple attributes at once using key => value pairs
39
+
40
+ - fast lookup of whether or not a class has defined a certain attribute
41
+
42
+ - attributes can be defined on objects on a per singleton basis as well
43
+
44
+ - getters acts as setters if an argument is given to them
45
+
46
+ - block caching, calling an attribute 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.1
53
+ - removed wrong dep on pervasives from gemspec.rb
54
+
55
+ 5.0.0
56
+ - added support for block caching. for example
57
+
58
+ - simple block caching:
59
+
60
+ class Filter
61
+ attribute :process
62
+ end
63
+
64
+ filter = Filter.new
65
+
66
+ filter.process{|line| line.upcase}
67
+
68
+ lines.each do |line|
69
+ p filter.process.call(line)
70
+ end
71
+
72
+ - using block caching to delay block evaluation/class-factory:
73
+
74
+ module MigrationDSL
75
+ attribute :migration
76
+
77
+ def migration_class
78
+ model = self
79
+
80
+ Class.new(::ActiveRecord::Migration) do
81
+ singleton_class =
82
+ class << self
83
+ self
84
+ end
85
+ singleton_class.module_eval{ attribute :model => model }
86
+ singleton_class.module_eval &model.migration
87
+ end
88
+ end
89
+ end
90
+
91
+ class Table < ActiveRecord::Base
92
+ extend MigrationDSL
93
+ end
94
+
95
+ class Jobs < Table
96
+ migration do
97
+ def up
98
+ create_table model.table_name, :primary_key => model.primary_key do |t|
99
+ t.column 'vinyl_shoes', :text
100
+ end
101
+ end
102
+
103
+ def down
104
+ create_table model.table_name
105
+ end
106
+ end
107
+ end
108
+
109
+ ...
110
+
111
+ JobsMigration = Jobs.migration_class
112
+
113
+ 4.1.0
114
+ - 4.0.0 introduced a bug where a query (foo?) would not initialize a var -
115
+ 4.1.0 fixes that
116
+
117
+ 4.0.0
118
+ - removed dependancy on, and bundle of, pervasives
119
+ - faster. as fast as normal method definition.
120
+ - faster lookup for MyClass.attributes.include?('foobar')
121
+
122
+ 3.7.0
123
+ small patch to use 'instance_variable_defined?' instead of defined?
124
+ keyword
125
+
126
+ 3.5.0
127
+ migrated to a pervasives based impl to attributes should work on any
128
+ object - even blankslate objects
129
+
130
+ 3.3.0
131
+
132
+ moved to an instance variable-less model using an module level closure for
133
+ the attributes list
134
+
135
+ SAMPLES
136
+
137
+ <========< samples/a.rb >========>
138
+
139
+ ~ > cat samples/a.rb
140
+
141
+ #
142
+ # basic usage is like attr, but note that attribute defines a suite of methods
143
+ #
144
+ require 'attributes'
145
+
146
+ class C
147
+ attribute 'a'
148
+ end
149
+
150
+ c = C.new
151
+
152
+ c.a = 42
153
+ p c.a #=> 42
154
+ p 'forty-two' if c.a? #=> 'forty-two'
155
+
156
+ #
157
+ # attributes works on object too
158
+ #
159
+ o = Object.new
160
+ o.attribute 'answer' => 42
161
+ p o.answer #=> 42
162
+
163
+ ~ > ruby samples/a.rb
164
+
165
+ 42
166
+ "forty-two"
167
+ 42
168
+
169
+
170
+ <========< samples/b.rb >========>
171
+
172
+ ~ > cat samples/b.rb
173
+
174
+ #
175
+ # default values may be given either directly or as a block which will be
176
+ # evaluated in the context of self. in both cases (value or block) the
177
+ # default is set only once and only if needed - it's a lazy evaluation. the
178
+ # 'banger' method can be used to re-initialize a variable at any point whether
179
+ # or not it's already been initialized.
180
+ #
181
+ require 'attributes'
182
+
183
+ class C
184
+ attribute :a => 42
185
+ attribute(:b){ Float a }
186
+ end
187
+
188
+ c = C.new
189
+ p c.a #=> 42
190
+ p c.b #=> 42.0
191
+
192
+ c.a = 43
193
+ p c.a #=> 43
194
+ c.a!
195
+ p c.a #=> 42
196
+
197
+ ~ > ruby samples/b.rb
198
+
199
+ 42
200
+ 42.0
201
+ 43
202
+ 42
203
+
204
+
205
+ <========< samples/c.rb >========>
206
+
207
+ ~ > cat samples/c.rb
208
+
209
+ #
210
+ # multiple values may by given, plain names and key/val pairs may be mixed.
211
+ #
212
+ require 'attributes'
213
+
214
+ class C
215
+ attributes 'x', 'y' => 0b101000, 'z' => 0b10
216
+ end
217
+
218
+ c = C.new
219
+ c.x = c.y + c.z
220
+ p c.x #=> 42
221
+
222
+ ~ > ruby samples/c.rb
223
+
224
+ 42
225
+
226
+
227
+ <========< samples/d.rb >========>
228
+
229
+ ~ > cat samples/d.rb
230
+
231
+ #
232
+ # a nice feature is that all attributes are enumerated in the class. this,
233
+ # combined with the fact that the getter method is defined so as to delegate
234
+ # to the setter when an argument is given, means bulk initialization and/or
235
+ # attribute traversal is very easy.
236
+ #
237
+ require 'attributes'
238
+
239
+ class C
240
+ attributes %w( x y z )
241
+
242
+ def attributes
243
+ self.class.attributes
244
+ end
245
+
246
+ def initialize
247
+ attributes.each_with_index{|a,i| send a, i}
248
+ end
249
+
250
+ def to_hash
251
+ attributes.inject({}){|h,a| h.update a => send(a)}
252
+ end
253
+
254
+ def inspect
255
+ to_hash.inspect
256
+ end
257
+ end
258
+
259
+ c = C.new
260
+ p c.attributes
261
+ p c
262
+
263
+ c.x 'forty-two'
264
+ p c.x
265
+
266
+ ~ > ruby samples/d.rb
267
+
268
+ ["x", "y", "z"]
269
+ {"x"=>0, "y"=>1, "z"=>2}
270
+ "forty-two"
271
+
272
+
273
+ <========< samples/e.rb >========>
274
+
275
+ ~ > cat samples/e.rb
276
+
277
+ #
278
+ # my favourite element of attributes is that getters can also be setters.
279
+ # this allows incredibly clean looking code like
280
+ #
281
+ require 'attributes'
282
+
283
+ class Config
284
+ attributes %w( host port)
285
+ def initialize(&block) instance_eval &block end
286
+ end
287
+
288
+ conf = Config.new{
289
+ host 'codeforpeople.org'
290
+
291
+ port 80
292
+ }
293
+
294
+ p conf
295
+
296
+ ~ > ruby samples/e.rb
297
+
298
+ #<Config:0x1fb58 @port=80, @host="codeforpeople.org">
299
+
300
+
301
+ <========< samples/f.rb >========>
302
+
303
+ ~ > cat samples/f.rb
304
+
305
+ #
306
+ # of course attributes works as well at class/module level as at instance
307
+ # level
308
+ #
309
+ require 'attributes'
310
+
311
+ module Logging
312
+ Level_names = {
313
+ 0 => 'INFO',
314
+ # ...
315
+ 42 => 'DEBUG',
316
+ }
317
+
318
+ class << self
319
+ attribute 'level' => 42
320
+ attribute('level_name'){ Level_names[level] }
321
+ end
322
+ end
323
+
324
+ p Logging.level
325
+ p Logging.level_name
326
+
327
+ ~ > ruby samples/f.rb
328
+
329
+ 42
330
+ "DEBUG"
331
+
data/README.tmpl ADDED
@@ -0,0 +1,133 @@
1
+ NAME
2
+ attributes.rb
3
+
4
+ INSTALL
5
+ gem install attributes
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
+ attributes.rb provides a set of attr_* like method with several user
14
+ friendly additions. attributes.rb is similar to the traits.rb package but
15
+ sacrifices a few features for simplicity of implementation.
16
+
17
+ the implementation of attributes.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 lib
24
+
25
+ key features provided by attributes 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 attributes they've defined and this information is
32
+ available to client code
33
+
34
+ - a whole suite of methods is defined by calls to #attributes including
35
+ getter, setter, query (var?) and banger (var! - which forces
36
+ re-initialization from the default value)
37
+
38
+ - ability to define multiple attributes at once using key => value pairs
39
+
40
+ - fast lookup of whether or not a class has defined a certain attribute
41
+
42
+ - attributes can be defined on objects on a per singleton basis as well
43
+
44
+ - getters acts as setters if an argument is given to them
45
+
46
+ - block caching, calling an attribute 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
+ - added support for block caching. for example
54
+
55
+ - simple block caching:
56
+
57
+ class Filter
58
+ attribute :process
59
+ end
60
+
61
+ filter = Filter.new
62
+
63
+ filter.process{|line| line.upcase}
64
+
65
+ lines.each do |line|
66
+ p filter.process.call(line)
67
+ end
68
+
69
+ - using block caching to delay block evaluation/class-factory:
70
+
71
+ module MigrationDSL
72
+ attribute :migration
73
+
74
+ def migration_class
75
+ model = self
76
+
77
+ Class.new(::ActiveRecord::Migration) do
78
+ singleton_class =
79
+ class << self
80
+ self
81
+ end
82
+ singleton_class.module_eval{ attribute :model => model }
83
+ singleton_class.module_eval &model.migration
84
+ end
85
+ end
86
+ end
87
+
88
+ class Table < ActiveRecord::Base
89
+ extend MigrationDSL
90
+ end
91
+
92
+ class Jobs < Table
93
+ migration do
94
+ def up
95
+ create_table model.table_name, :primary_key => model.primary_key do |t|
96
+ t.column 'vinyl_shoes', :text
97
+ end
98
+ end
99
+
100
+ def down
101
+ create_table model.table_name
102
+ end
103
+ end
104
+ end
105
+
106
+ ...
107
+
108
+ JobsMigration = Jobs.migration_class
109
+
110
+ 4.1.0
111
+ - 4.0.0 introduced a bug where a query (foo?) would not initialize a var -
112
+ 4.1.0 fixes that
113
+
114
+ 4.0.0
115
+ - removed dependancy on, and bundle of, pervasives
116
+ - faster. as fast as normal method definition.
117
+ - faster lookup for MyClass.attributes.include?('foobar')
118
+
119
+ 3.7.0
120
+ small patch to use 'instance_variable_defined?' instead of defined?
121
+ keyword
122
+
123
+ 3.5.0
124
+ migrated to a pervasives based impl to attributes should work on any
125
+ object - even blankslate objects
126
+
127
+ 3.3.0
128
+
129
+ moved to an instance variable-less model using an module level closure for
130
+ the attributes list
131
+
132
+ SAMPLES
133
+ @samples
data/a.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'attributes'
2
+
3
+ module M
4
+ p(( attribute 'a' => 42 ))
5
+ p(( attribute('b'){ "forty-two (#{ self })" } ))
6
+ end
7
+ p M.attributes
8
+ p M.attributes.include?('a')
9
+ p M.attributes.include?('b')
10
+ p M.attributes.include?('c')
11
+
12
+ class C
13
+ include M
14
+ end
15
+ p C.new.a
16
+ p C.new.b
17
+ p C.attributes
18
+ p C.attributes.include?('a')
19
+ p C.attributes.include?('b')
20
+ p C.attributes.include?('c')
21
+
22
+ class B < C
23
+ end
24
+ p B.new.a
25
+ p B.new.b
26
+ p B.attributes
27
+ p B.attributes.include?('a')
28
+ p B.attributes.include?('b')
29
+ p B.attributes.include?('c')
data/b.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'lib/attributes.rb'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+ require 'yaml'
5
+
6
+ options = YAML.load <<-txt
7
+ adapter: postgresql
8
+ database: votelink
9
+ username: www
10
+ host: localhost
11
+ encoding: UTF8
12
+ txt
13
+ ActiveRecord::Base.establish_connection options
14
+
15
+ module MigrationDSL
16
+ attribute :migration
17
+
18
+ def migration_class
19
+ model = self
20
+ Class.new(::ActiveRecord::Migration) do
21
+ singleton_class =
22
+ class << self
23
+ self
24
+ end
25
+ singleton_class.module_eval{ attribute :model => model }
26
+ singleton_class.module_eval &model.migration
27
+ end
28
+ end
29
+ end
30
+
31
+ class Table < ActiveRecord::Base
32
+ extend MigrationDSL
33
+ end
34
+
35
+ class Jobs < Table
36
+ migration do
37
+ def up
38
+ create_table model.table_name, :primary_key => model.primary_key do |t|
39
+ t.column 'rockin', :text
40
+ end
41
+ end
42
+
43
+ def down
44
+ create_table model.table_name
45
+ end
46
+ end
47
+ end
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
+ lib = 'attributes'
9
+ spec.name = 'attributes1'
10
+ spec.version = version
11
+ spec.platform = Gem::Platform::RUBY
12
+ spec.summary = lib
13
+
14
+ spec.files = Dir::glob "**/**"
15
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
16
+
17
+ spec.require_path = "lib"
18
+ spec.autorequire = lib
19
+
20
+ spec.has_rdoc = File::exist? "doc"
21
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
22
+ #spec.add_dependency 'pervasives', '>= 1.0'
23
+
24
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
25
+
26
+ spec.author = "Mitesh Jain"
27
+ spec.email = "mitijain123@gmail.com"
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,206 @@
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 f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -s, --sudo
160
+ -h, --help
161
+ usage
162
+
163
+ begin
164
+ while switch = ARGV.switch
165
+ case switch
166
+ when '-d', '--destdir'
167
+ libdir = ARGV.req_arg
168
+ when '-l', '--libdir'
169
+ libdir = ARGV.req_arg
170
+ when '-b', '--bindir'
171
+ bindir = ARGV.req_arg
172
+ when '-r', '--ruby'
173
+ $ruby = ARGV.req_arg
174
+ when '-n', '--no_linkify'
175
+ no_linkify = true
176
+ when '-s', '--sudo'
177
+ sudo = 'sudo'
178
+ when '-h', '--help'
179
+ help = true
180
+ else
181
+ raise "unknown switch #{switch.dump}"
182
+ end
183
+ end
184
+ rescue
185
+ STDERR.puts $!.to_s
186
+ STDERR.puts usage
187
+ exit 1
188
+ end
189
+
190
+ if help
191
+ STDOUT.puts usage
192
+ exit
193
+ end
194
+
195
+ unless no_linkify
196
+ linked = linkify('lib') + linkify('bin')
197
+ end
198
+
199
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
200
+
201
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
202
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
203
+
204
+ if linked
205
+ linked.each{|path| File::rm_f path}
206
+ end
@@ -0,0 +1,118 @@
1
+ module Attributes
2
+ Attributes::VERSION = '5.0.0' unless defined? Attributes::VERSION
3
+ def self.version() Attributes::VERSION end
4
+
5
+ class List < ::Array
6
+ def << element
7
+ super
8
+ self
9
+ ensure
10
+ uniq!
11
+ index!
12
+ end
13
+ def index!
14
+ @index ||= Hash.new
15
+ each{|element| @index[element] = true}
16
+ end
17
+ def include? element
18
+ @index ||= Hash.new
19
+ @index[element] ? true : false
20
+ end
21
+ def initializers
22
+ @initializers ||= Hash.new
23
+ end
24
+ end
25
+
26
+ def attributes *a, &b
27
+ unless a.empty?
28
+ returned = Hash.new
29
+
30
+ hashes, names = a.partition{|x| Hash === x}
31
+ names_and_defaults = {}
32
+ hashes.each{|h| names_and_defaults.update h}
33
+ names.flatten.compact.each{|name| names_and_defaults.update name => nil}
34
+
35
+ initializers = __attributes__.initializers
36
+
37
+ names_and_defaults.each do |name, default|
38
+ raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
39
+ name = name.to_s
40
+
41
+ initialize = b || lambda { default }
42
+ initializer = lambda do |this|
43
+ Object.instance_method('instance_eval').bind(this).call &initialize
44
+ end
45
+ initializer_id = initializer.object_id
46
+ __attributes__.initializers[name] = initializer
47
+
48
+ module_eval <<-code
49
+ def #{ name }=(*value, &block)
50
+ value.unshift block if block
51
+ @#{ name } = value.first
52
+ end
53
+ code
54
+
55
+ module_eval <<-code
56
+ def #{ name }(*value, &block)
57
+ value.unshift block if block
58
+ return self.send('#{ name }=', value.first) unless value.empty?
59
+ #{ name }! unless defined? @#{ name }
60
+ @#{ name }
61
+ end
62
+ code
63
+
64
+ module_eval <<-code
65
+ def #{ name }!
66
+ initializer = ObjectSpace._id2ref #{ initializer_id }
67
+ self.#{ name } = initializer.call(self)
68
+ @#{ name }
69
+ end
70
+ code
71
+
72
+ module_eval <<-code
73
+ def #{ name }?
74
+ #{ name }
75
+ end
76
+ code
77
+
78
+ attributes << name
79
+ returned[name] = initializer
80
+ end
81
+
82
+ returned
83
+ else
84
+ begin
85
+ __attribute_list__
86
+ rescue NameError
87
+ singleton_class =
88
+ class << self
89
+ self
90
+ end
91
+ klass = self
92
+ singleton_class.module_eval do
93
+ attribute_list = List.new
94
+ define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
95
+ alias_method '__attribute_list__', 'attribute_list'
96
+ end
97
+ __attribute_list__
98
+ end
99
+ end
100
+ end
101
+
102
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
103
+ end
104
+
105
+ class Object
106
+ def attributes *a, &b
107
+ sc =
108
+ class << self
109
+ self
110
+ end
111
+ sc.attributes *a, &b
112
+ end
113
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
114
+ end
115
+
116
+ class Module
117
+ include Attributes
118
+ end
data/lib/attributes.rb ADDED
@@ -0,0 +1,118 @@
1
+ module Attributes
2
+ Attributes::VERSION = '5.0.0' unless defined? Attributes::VERSION
3
+ def self.version() Attributes::VERSION end
4
+
5
+ class List < ::Array
6
+ def << element
7
+ super
8
+ self
9
+ ensure
10
+ uniq!
11
+ index!
12
+ end
13
+ def index!
14
+ @index ||= Hash.new
15
+ each{|element| @index[element] = true}
16
+ end
17
+ def include? element
18
+ @index ||= Hash.new
19
+ @index[element] ? true : false
20
+ end
21
+ def initializers
22
+ @initializers ||= Hash.new
23
+ end
24
+ end
25
+
26
+ def attributes *a, &b
27
+ unless a.empty?
28
+ returned = Hash.new
29
+
30
+ hashes, names = a.partition{|x| Hash === x}
31
+ names_and_defaults = {}
32
+ hashes.each{|h| names_and_defaults.update h}
33
+ names.flatten.compact.each{|name| names_and_defaults.update name => nil}
34
+
35
+ initializers = __attributes__.initializers
36
+
37
+ names_and_defaults.each do |name, default|
38
+ raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
39
+ name = name.to_s
40
+
41
+ initialize = b || lambda { default }
42
+ initializer = lambda do |this|
43
+ Object.instance_method('instance_eval').bind(this).call &initialize
44
+ end
45
+ initializer_id = initializer.object_id
46
+ __attributes__.initializers[name] = initializer
47
+
48
+ module_eval <<-code
49
+ def #{ name }=(*value, &block)
50
+ value.unshift block if block
51
+ @#{ name } = value.first
52
+ end
53
+ code
54
+
55
+ module_eval <<-code
56
+ def #{ name }(*value, &block)
57
+ value.unshift block if block
58
+ return self.send('#{ name }=', value.first) unless value.empty?
59
+ #{ name }! unless defined? @#{ name }
60
+ @#{ name }
61
+ end
62
+ code
63
+
64
+ module_eval <<-code
65
+ def #{ name }!
66
+ initializer = ObjectSpace._id2ref #{ initializer_id }
67
+ self.#{ name } = initializer.call(self)
68
+ @#{ name }
69
+ end
70
+ code
71
+
72
+ module_eval <<-code
73
+ def #{ name }?
74
+ #{ name }
75
+ end
76
+ code
77
+
78
+ attributes << name
79
+ returned[name] = initializer
80
+ end
81
+
82
+ returned
83
+ else
84
+ begin
85
+ __attribute_list__
86
+ rescue NameError
87
+ singleton_class =
88
+ class << self
89
+ self
90
+ end
91
+ klass = self
92
+ singleton_class.module_eval do
93
+ attribute_list = List.new
94
+ define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
95
+ alias_method '__attribute_list__', 'attribute_list'
96
+ end
97
+ __attribute_list__
98
+ end
99
+ end
100
+ end
101
+
102
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
103
+ end
104
+
105
+ class Object
106
+ def attributes *a, &b
107
+ sc =
108
+ class << self
109
+ self
110
+ end
111
+ sc.attributes *a, &b
112
+ end
113
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
114
+ end
115
+
116
+ class Module
117
+ include Attributes
118
+ end
data/samples/a.rb ADDED
@@ -0,0 +1,21 @@
1
+ #
2
+ # basic usage is like attr, but note that attribute defines a suite of methods
3
+ #
4
+ require 'attributes'
5
+
6
+ class C
7
+ attribute '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
+ # attributes works on object too
18
+ #
19
+ o = Object.new
20
+ o.attribute '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 'attributes'
9
+
10
+ class C
11
+ attribute :a => 42
12
+ attribute(: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 'attributes'
5
+
6
+ class C
7
+ attributes '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 attributes 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
+ # attribute traversal is very easy.
6
+ #
7
+ require 'attributes'
8
+
9
+ class C
10
+ attributes %w( x y z )
11
+
12
+ def attributes
13
+ self.class.attributes
14
+ end
15
+
16
+ def initialize
17
+ attributes.each_with_index{|a,i| send a, i}
18
+ end
19
+
20
+ def to_hash
21
+ attributes.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.attributes
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 attributes is that getters can also be setters.
3
+ # this allows incredibly clean looking code like
4
+ #
5
+ require 'attributes'
6
+
7
+ class Config
8
+ attributes %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 attributes works as well at class/module level as at instance
3
+ # level
4
+ #
5
+ require 'attributes'
6
+
7
+ module Logging
8
+ Level_names = {
9
+ 0 => 'INFO',
10
+ # ...
11
+ 42 => 'DEBUG',
12
+ }
13
+
14
+ class << self
15
+ attribute 'level' => 42
16
+ attribute('level_name'){ Level_names[level] }
17
+ end
18
+ end
19
+
20
+ p Logging.level
21
+ p Logging.level_name
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attributes1
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mitesh Jain
9
+ autorequire: attributes
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-24 00:00:00.000000000Z
13
+ dependencies: []
14
+ description:
15
+ email: mitijain123@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - a.rb
21
+ - b.rb
22
+ - gemspec.rb
23
+ - gen_readme.rb
24
+ - install.rb
25
+ - lib/attributes-5.0.0.rb
26
+ - lib/attributes.rb
27
+ - README
28
+ - README.tmpl
29
+ - samples/a.rb
30
+ - samples/b.rb
31
+ - samples/c.rb
32
+ - samples/d.rb
33
+ - samples/e.rb
34
+ - samples/f.rb
35
+ homepage:
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.10
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: attributes
59
+ test_files: []