attributes1 5.0.2

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,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: []