attributes 3.7.0 → 4.0.0

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 CHANGED
@@ -11,17 +11,45 @@ URIS
11
11
  SYNOPSIS
12
12
  attributes.rb provides a set of attr_* like method with several user
13
13
  friendly additions. attributes.rb is similar to the traits.rb package but
14
- sacrifices a few features for simplicity of implementation: attributes.rb is
15
- only 42 lines of code.
14
+ sacrifices a few features for simplicity of implementation.
16
15
 
17
- the implimentation of attributes.rb borrows many of the best ideas from the
16
+ the implementation of attributes.rb borrows many of the best ideas from the
18
17
  metakoans.rb ruby quiz
19
18
 
20
19
  http://www.rubyquiz.com/quiz67.html
21
20
 
22
- in particular the solutions of Christian Neukirchen and Florian Gross.
21
+ in particular the solutions of Christian Neukirchen and Florian Gross along
22
+ with concepts from the original traits lib
23
+
24
+ key features provided by attributes are
25
+
26
+ - ability to specify default values for attrs and definition time. values
27
+ can be literal objects or blocks, which are evaluated in the context of
28
+ self to initialize the variable
29
+
30
+ - classes remember which attributes they've defined and this information is
31
+ available to client code
32
+
33
+ - a whole suite of methods is defined by calls to #attributes including
34
+ getter, setter, query (var?) and banger (var! - which forces
35
+ re-initialization from the default value)
36
+
37
+ - ability to define multiple attributes at once using key => value pairs
38
+
39
+ - fast lookup of whether or not a class has defined a certain attribute
40
+
41
+ - attributes can be defined on objects on a per singleton basis as well
42
+
43
+ - getters acts as setters if an argument is given to them
44
+
45
+ all this in < 100 lines of code
23
46
 
24
47
  HISTORY
48
+ 4.0.0
49
+ - removed dependancy on, and bundle of, pervasives
50
+ - faster. as fast as normal method definition.
51
+ - faster lookup for MyClass.attributes.include?('foobar')
52
+
25
53
  3.7.0
26
54
  small patch to use 'instance_variable_defined?' instead of defined?
27
55
  keyword
@@ -42,8 +70,7 @@ SAMPLES
42
70
  ~ > cat samples/a.rb
43
71
 
44
72
  #
45
- # basic usage is like attr, but note that attribute defines three methods,
46
- # getter, setter, and query
73
+ # basic usage is like attr, but note that attribute defines a suite of methods
47
74
  #
48
75
  require 'attributes'
49
76
 
@@ -53,16 +80,16 @@ SAMPLES
53
80
 
54
81
  c = C.new
55
82
 
56
- c.a = 42 # setter
57
- p c.a # getter
58
- p 'forty-two' if c.a? # query
83
+ c.a = 42
84
+ p c.a #=> 42
85
+ p 'forty-two' if c.a? #=> 'forty-two'
59
86
 
60
87
  #
61
- # also not that attribute(s) works as well for objects as classes
88
+ # attributes works on object too
62
89
  #
63
90
  o = Object.new
64
91
  o.attribute 'answer' => 42
65
- p o.answer
92
+ p o.answer #=> 42
66
93
 
67
94
  ~ > ruby samples/a.rb
68
95
 
@@ -78,7 +105,9 @@ SAMPLES
78
105
  #
79
106
  # default values may be given either directly or as a block which will be
80
107
  # evaluated in the context of self. in both cases (value or block) the
81
- # default is set only once and only if needed - it's a lazy evaluation.
108
+ # default is set only once and only if needed - it's a lazy evaluation. the
109
+ # 'banger' method can be used to re-initialize a variable at any point whether
110
+ # or not it's already been initialized.
82
111
  #
83
112
  require 'attributes'
84
113
 
@@ -88,14 +117,20 @@ SAMPLES
88
117
  end
89
118
 
90
119
  c = C.new
120
+ p c.a #=> 42
121
+ p c.b #=> 42.0
91
122
 
92
- p c.a
93
- p c.b
123
+ c.a = 43
124
+ p c.a #=> 43
125
+ c.a!
126
+ p c.a #=> 42
94
127
 
95
128
  ~ > ruby samples/b.rb
96
129
 
97
130
  42
98
131
  42.0
132
+ 43
133
+ 42
99
134
 
100
135
 
101
136
  <========< samples/c.rb >========>
@@ -113,7 +148,7 @@ SAMPLES
113
148
 
114
149
  c = C.new
115
150
  c.x = c.y + c.z
116
- p c.x
151
+ p c.x #=> 42
117
152
 
118
153
  ~ > ruby samples/c.rb
119
154
 
@@ -191,5 +226,5 @@ SAMPLES
191
226
 
192
227
  ~ > ruby samples/e.rb
193
228
 
194
- #<Config:0x1e834 @port=80, @host="codeforpeople.org">
229
+ #<Config:0x20080 @port=80, @host="codeforpeople.org">
195
230
 
@@ -11,17 +11,45 @@ URIS
11
11
  SYNOPSIS
12
12
  attributes.rb provides a set of attr_* like method with several user
13
13
  friendly additions. attributes.rb is similar to the traits.rb package but
14
- sacrifices a few features for simplicity of implementation: attributes.rb is
15
- only 42 lines of code.
14
+ sacrifices a few features for simplicity of implementation.
16
15
 
17
- the implimentation of attributes.rb borrows many of the best ideas from the
16
+ the implementation of attributes.rb borrows many of the best ideas from the
18
17
  metakoans.rb ruby quiz
19
18
 
20
19
  http://www.rubyquiz.com/quiz67.html
21
20
 
22
- in particular the solutions of Christian Neukirchen and Florian Gross.
21
+ in particular the solutions of Christian Neukirchen and Florian Gross along
22
+ with concepts from the original traits lib
23
+
24
+ key features provided by attributes are
25
+
26
+ - ability to specify default values for attrs and definition time. values
27
+ can be literal objects or blocks, which are evaluated in the context of
28
+ self to initialize the variable
29
+
30
+ - classes remember which attributes they've defined and this information is
31
+ available to client code
32
+
33
+ - a whole suite of methods is defined by calls to #attributes including
34
+ getter, setter, query (var?) and banger (var! - which forces
35
+ re-initialization from the default value)
36
+
37
+ - ability to define multiple attributes at once using key => value pairs
38
+
39
+ - fast lookup of whether or not a class has defined a certain attribute
40
+
41
+ - attributes can be defined on objects on a per singleton basis as well
42
+
43
+ - getters acts as setters if an argument is given to them
44
+
45
+ all this in < 100 lines of code
23
46
 
24
47
  HISTORY
48
+ 4.0.0
49
+ - removed dependancy on, and bundle of, pervasives
50
+ - faster. as fast as normal method definition.
51
+ - faster lookup for MyClass.attributes.include?('foobar')
52
+
25
53
  3.7.0
26
54
  small patch to use 'instance_variable_defined?' instead of defined?
27
55
  keyword
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')
@@ -0,0 +1,110 @@
1
+ module Attributes
2
+ Attributes::VERSION = '4.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)
50
+ @#{ name } = value
51
+ end
52
+
53
+ def #{ name }(*value)
54
+ return self.#{ name } = value.first unless value.empty?
55
+ #{ name }! unless defined? @#{ name }
56
+ @#{ name }
57
+ end
58
+
59
+ def #{ name }!
60
+ initializer = ObjectSpace._id2ref #{ initializer_id }
61
+ self.#{ name } = initializer.call(self)
62
+ @#{ name }
63
+ end
64
+
65
+ def #{ name }?
66
+ defined? @#{ name } and #{ name }
67
+ end
68
+ code
69
+
70
+ attributes << name
71
+ returned[name] = initializer
72
+ end
73
+
74
+ returned
75
+ else
76
+ begin
77
+ __attribute_list__
78
+ rescue NameError
79
+ singleton_class =
80
+ class << self
81
+ self
82
+ end
83
+ klass = self
84
+ singleton_class.module_eval do
85
+ attribute_list = List.new
86
+ define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
87
+ alias_method '__attribute_list__', 'attribute_list'
88
+ end
89
+ __attribute_list__
90
+ end
91
+ end
92
+ end
93
+
94
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
95
+ end
96
+
97
+ class Object
98
+ def attributes *a, &b
99
+ sc =
100
+ class << self
101
+ self
102
+ end
103
+ sc.attributes *a, &b
104
+ end
105
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
106
+ end
107
+
108
+ class Module
109
+ include Attributes
110
+ end
@@ -1,46 +1,77 @@
1
1
  module Attributes
2
- VERSION = '3.7.0'
3
- def self.version() VERSION end
2
+ Attributes::VERSION = '4.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
4
25
 
5
26
  def attributes *a, &b
6
27
  unless a.empty?
7
- hashes, names = a.partition{|x| Hash === x}
28
+ returned = Hash.new
8
29
 
30
+ hashes, names = a.partition{|x| Hash === x}
9
31
  names_and_defaults = {}
10
32
  hashes.each{|h| names_and_defaults.update h}
11
33
  names.flatten.compact.each{|name| names_and_defaults.update name => nil}
12
34
 
13
- names_and_defaults.each do |name, default|
14
- init = b || lambda { default }
15
- ivar, getter, setter, query, banger =
16
- "@#{ name }", "#{ name }", "#{ name }=", "#{ name }?", "#{ name }!"
35
+ initializers = __attributes__.initializers
17
36
 
18
- raise NameError, "bad instance variable name '#{ ivar }'" if ivar =~ %r/[!?=]$/o
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
19
40
 
20
- define_method(setter) do |value|
21
- __pervasive__('instance_variable_set', ivar, value)
41
+ initialize = b || lambda { default }
42
+ initializer = lambda do |this|
43
+ Object.instance_method('instance_eval').bind(this).call &initialize
22
44
  end
45
+ initializer_id = initializer.object_id
46
+ __attributes__.initializers[name] = initializer
23
47
 
24
- define_method(getter) do |*value|
25
- unless value.empty?
26
- __pervasive__('send', setter, value.shift)
27
- else
28
- defined = __pervasive__('instance_variable_defined?', "#{ ivar }")
29
- __pervasive__('send', setter, __pervasive__('instance_eval', &init)) unless defined
30
- __pervasive__('instance_variable_get', ivar)
48
+ module_eval <<-code
49
+ def #{ name }=(value)
50
+ @#{ name } = value
31
51
  end
32
- end
33
52
 
34
- define_method(banger) do
35
- __pervasive__('send', setter, __pervasive__('instance_eval', &init))
36
- __pervasive__('instance_variable_get', ivar)
37
- end
53
+ def #{ name }(*value)
54
+ return self.#{ name } = value.first unless value.empty?
55
+ #{ name }! unless defined? @#{ name }
56
+ @#{ name }
57
+ end
58
+
59
+ def #{ name }!
60
+ initializer = ObjectSpace._id2ref #{ initializer_id }
61
+ self.#{ name } = initializer.call(self)
62
+ @#{ name }
63
+ end
38
64
 
39
- alias_method query, getter
65
+ def #{ name }?
66
+ defined? @#{ name } and #{ name }
67
+ end
68
+ code
40
69
 
41
- (attributes << name.to_s).uniq!
42
- attributes
70
+ attributes << name
71
+ returned[name] = initializer
43
72
  end
73
+
74
+ returned
44
75
  else
45
76
  begin
46
77
  __attribute_list__
@@ -51,7 +82,7 @@ module Attributes
51
82
  end
52
83
  klass = self
53
84
  singleton_class.module_eval do
54
- attribute_list = []
85
+ attribute_list = List.new
55
86
  define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
56
87
  alias_method '__attribute_list__', 'attribute_list'
57
88
  end
@@ -77,47 +108,3 @@ end
77
108
  class Module
78
109
  include Attributes
79
110
  end
80
-
81
- BEGIN {
82
- unless defined? Pervasives
83
- begin
84
- require 'pervasives'
85
- rescue LoadError
86
- module Pervasives
87
- VERSION = "1.0.0"
88
- def self.version() VERSION end
89
- class ::Class
90
- def __pervasive__ m, *a, &b
91
- (( Class.instance_method(m) rescue
92
- Module.instance_method(m) rescue
93
- Object.instance_method(m) )).bind(self).call(*a, &b)
94
- end
95
- end
96
- class ::Module
97
- def __pervasive__ m, *a, &b
98
- (( Module.instance_method(m) rescue
99
- Object.instance_method(m) )).bind(self).call(*a, &b)
100
- end
101
- end
102
- class ::Object
103
- def __pervasive__ m, *a, &b
104
- (( Object.instance_method(m) )).bind(self).call(*a, &b)
105
- end
106
- end
107
-
108
- class Proxy
109
- instance_methods.each{|m| undef_method m unless m[%r/__/]}
110
- def initialize obj
111
- @obj = obj
112
- end
113
- def method_missing m, *a, &b
114
- @obj.__pervasive__ m, *a, &b
115
- end
116
- def __obj__
117
- @obj
118
- end
119
- end
120
- end
121
- end
122
- end
123
- }
@@ -1,6 +1,5 @@
1
1
  #
2
- # basic usage is like attr, but note that attribute defines three methods,
3
- # getter, setter, and query
2
+ # basic usage is like attr, but note that attribute defines a suite of methods
4
3
  #
5
4
  require 'attributes'
6
5
 
@@ -10,13 +9,13 @@
10
9
 
11
10
  c = C.new
12
11
 
13
- c.a = 42 # setter
14
- p c.a # getter
15
- p 'forty-two' if c.a? # query
12
+ c.a = 42
13
+ p c.a #=> 42
14
+ p 'forty-two' if c.a? #=> 'forty-two'
16
15
 
17
16
  #
18
- # also not that attribute(s) works as well for objects as classes
17
+ # attributes works on object too
19
18
  #
20
19
  o = Object.new
21
20
  o.attribute 'answer' => 42
22
- p o.answer
21
+ p o.answer #=> 42
@@ -1,7 +1,9 @@
1
1
  #
2
2
  # default values may be given either directly or as a block which will be
3
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.
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.
5
7
  #
6
8
  require 'attributes'
7
9
 
@@ -11,6 +13,10 @@
11
13
  end
12
14
 
13
15
  c = C.new
16
+ p c.a #=> 42
17
+ p c.b #=> 42.0
14
18
 
15
- p c.a
16
- p c.b
19
+ c.a = 43
20
+ p c.a #=> 43
21
+ c.a!
22
+ p c.a #=> 42
@@ -9,4 +9,4 @@
9
9
 
10
10
  c = C.new
11
11
  c.x = c.y + c.z
12
- p c.x
12
+ p c.x #=> 42
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: attributes
5
5
  version: !ruby/object:Gem::Version
6
- version: 3.7.0
7
- date: 2007-09-15 00:00:00 -06:00
6
+ version: 4.0.0
7
+ date: 2007-10-10 00:00:00 -06:00
8
8
  summary: attributes
9
9
  require_paths:
10
10
  - lib
@@ -29,11 +29,12 @@ post_install_message:
29
29
  authors:
30
30
  - Ara T. Howard
31
31
  files:
32
+ - a.rb
32
33
  - gemspec.rb
33
34
  - gen_readme.rb
34
35
  - install.rb
35
36
  - lib
36
- - lib/attributes-3.7.0.rb
37
+ - lib/attributes-4.0.0.rb
37
38
  - lib/attributes.rb
38
39
  - README
39
40
  - README.tmpl
@@ -1,123 +0,0 @@
1
- module Attributes
2
- VERSION = '3.7.0'
3
- def self.version() VERSION end
4
-
5
- def attributes *a, &b
6
- unless a.empty?
7
- hashes, names = a.partition{|x| Hash === x}
8
-
9
- names_and_defaults = {}
10
- hashes.each{|h| names_and_defaults.update h}
11
- names.flatten.compact.each{|name| names_and_defaults.update name => nil}
12
-
13
- names_and_defaults.each do |name, default|
14
- init = b || lambda { default }
15
- ivar, getter, setter, query, banger =
16
- "@#{ name }", "#{ name }", "#{ name }=", "#{ name }?", "#{ name }!"
17
-
18
- raise NameError, "bad instance variable name '#{ ivar }'" if ivar =~ %r/[!?=]$/o
19
-
20
- define_method(setter) do |value|
21
- __pervasive__('instance_variable_set', ivar, value)
22
- end
23
-
24
- define_method(getter) do |*value|
25
- unless value.empty?
26
- __pervasive__('send', setter, value.shift)
27
- else
28
- defined = __pervasive__('instance_variable_defined?', "#{ ivar }")
29
- __pervasive__('send', setter, __pervasive__('instance_eval', &init)) unless defined
30
- __pervasive__('instance_variable_get', ivar)
31
- end
32
- end
33
-
34
- define_method(banger) do
35
- __pervasive__('send', setter, __pervasive__('instance_eval', &init))
36
- __pervasive__('instance_variable_get', ivar)
37
- end
38
-
39
- alias_method query, getter
40
-
41
- (attributes << name.to_s).uniq!
42
- attributes
43
- end
44
- else
45
- begin
46
- __attribute_list__
47
- rescue NameError
48
- singleton_class =
49
- class << self
50
- self
51
- end
52
- klass = self
53
- singleton_class.module_eval do
54
- attribute_list = []
55
- define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
56
- alias_method '__attribute_list__', 'attribute_list'
57
- end
58
- __attribute_list__
59
- end
60
- end
61
- end
62
-
63
- %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
64
- end
65
-
66
- class Object
67
- def attributes *a, &b
68
- sc =
69
- class << self
70
- self
71
- end
72
- sc.attributes *a, &b
73
- end
74
- %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
75
- end
76
-
77
- class Module
78
- include Attributes
79
- end
80
-
81
- BEGIN {
82
- unless defined? Pervasives
83
- begin
84
- require 'pervasives'
85
- rescue LoadError
86
- module Pervasives
87
- VERSION = "1.0.0"
88
- def self.version() VERSION end
89
- class ::Class
90
- def __pervasive__ m, *a, &b
91
- (( Class.instance_method(m) rescue
92
- Module.instance_method(m) rescue
93
- Object.instance_method(m) )).bind(self).call(*a, &b)
94
- end
95
- end
96
- class ::Module
97
- def __pervasive__ m, *a, &b
98
- (( Module.instance_method(m) rescue
99
- Object.instance_method(m) )).bind(self).call(*a, &b)
100
- end
101
- end
102
- class ::Object
103
- def __pervasive__ m, *a, &b
104
- (( Object.instance_method(m) )).bind(self).call(*a, &b)
105
- end
106
- end
107
-
108
- class Proxy
109
- instance_methods.each{|m| undef_method m unless m[%r/__/]}
110
- def initialize obj
111
- @obj = obj
112
- end
113
- def method_missing m, *a, &b
114
- @obj.__pervasive__ m, *a, &b
115
- end
116
- def __obj__
117
- @obj
118
- end
119
- end
120
- end
121
- end
122
- end
123
- }