sstruct 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.
@@ -0,0 +1,204 @@
1
+
2
+ SuperStruct
3
+ Hal Fulton
4
+ Version 1.0
5
+ License: The Ruby License
6
+
7
+ This is an easy way to create Struct-like classes; it converts easily
8
+ between hashes and arrays, and it allows OpenStruct-like dynamic naming
9
+ of members.
10
+
11
+ Unlike Struct, it creates a "real" class, and it has real instance variables
12
+ with predictable names.
13
+
14
+ A basic limitation is that the hash keys must be legal method names (unless
15
+ used with send()).
16
+
17
+ Basically, ss["alpha"], ss[:alpha], and ss.alpha all mean the same.
18
+
19
+
20
+ NOTES:
21
+
22
+
23
+ It's like a Struct...
24
+ - you can pass in a list of symbols for accessors
25
+ - it will create a class for you
26
+ but...
27
+ - you don't have to pass in the class name
28
+ - it returns a "real" class
29
+ . instance variables have the expected names
30
+ . you can reopen and add methods
31
+ - it doesn't go into the Struct:: namespace
32
+ - it preserves the order of the fields
33
+ - you can use Strings instead of Symbols for the names
34
+
35
+ It's like an Array...
36
+ - you can access the items by [number] and [number]=
37
+ but...
38
+ - you can also access the items by ["name"] and ["name"]=
39
+ - you can access the items by accessors
40
+
41
+ It's like an OpenStruct...
42
+ - (if you use .open instead of .new) you can add fields
43
+ automatically with x.field or x.field=val
44
+ but...
45
+ - you can initialize it like a Struct
46
+ - it preserves the order of the fields
47
+
48
+ It's like a Hash...
49
+ - data can be accessed by ["name"]
50
+ but...
51
+ - order (of entry or creation) is preserved
52
+ - arbitrary objects are not allowed (it does obj.to_str or obj.to_s)
53
+ - strings must be valid method names
54
+
55
+ It's like Ara Howard's Named Array...
56
+ - we can access elements by ["name"] or ["name"]=
57
+ but...
58
+ - you can access the items by accessors
59
+ - strings must be valid method names
60
+
61
+ It's like Florian Gross's Keyed List...
62
+ (to be done)
63
+ but...
64
+ - it preserves the order of the fields
65
+
66
+
67
+ Some examples: (see test cases)
68
+ --------------
69
+
70
+ # Need not assign to existing fields (default to nil)
71
+ myStruct = SuperStruct.new(:alpha)
72
+ x = myStruct.new
73
+ x.alpha # nil
74
+
75
+ # A value assigned at construction may be retrieved
76
+ myStruct = SuperStruct.new(:alpha)
77
+ x = myStruct.new(234)
78
+ x.alpha # 234
79
+
80
+ # Unassigned fields are nil
81
+ myStruct = SuperStruct.new(:alpha,:beta)
82
+ x = myStruct.new(234)
83
+ x.beta # nil
84
+
85
+ # An open structure may not construct with nonexistent fields
86
+ myStruct = SuperStruct.open
87
+ x = myStruct.new(234) # error
88
+
89
+ # An open structure may assign fields not previously existing
90
+ myStruct = SuperStruct.open
91
+ x = myStruct.new
92
+ x.foo = 123
93
+ x.bar = 456
94
+
95
+ # The act of retrieving a nonexistent field from an open struct will
96
+ # create that field
97
+ myStruct = SuperStruct.open
98
+ x = myStruct.new
99
+ x.foo # nil
100
+
101
+ # A field (in an open struct) that is unassigned will be nil
102
+ myStruct = SuperStruct.open
103
+ x = myStruct.new
104
+ y = x.foobar
105
+
106
+ # A struct created with new rather than open cannot reference nonexistent
107
+ # fields
108
+ myStruct = SuperStruct.new
109
+ x = myStruct.new
110
+ x.foo # error
111
+
112
+ # Adding a field to a struct will create a writer and reader for that field
113
+
114
+ # An open struct will also create a writer and a reader together
115
+
116
+ # A field has a real writer and reader corresponding to it
117
+
118
+ # A string will work as well as a symbol
119
+ myStruct = SuperStruct.new("alpha")
120
+
121
+ # to_a will return an array of values
122
+ myStruct = SuperStruct.new("alpha","beta","gamma")
123
+ x = myStruct.new(7,8,9)
124
+ assert(x.to_a == [7,8,9])
125
+
126
+ # Instance method 'members' will return a list of members (as strings)
127
+ myStruct = SuperStruct.new(:alpha,"beta")
128
+ x = myStruct.new
129
+ assert_equal(["alpha","beta"],x.members)
130
+
131
+ # Class method 'members' will return a list of members (as strings)
132
+ myStruct = SuperStruct.new(:alpha,"beta")
133
+ assert_equal(["alpha","beta"],myStruct.members)
134
+
135
+ # to_ary will allow a struct to be treated like an array in
136
+ # multiple assignment
137
+ myStruct = SuperStruct.new("alpha","beta","gamma")
138
+ x = myStruct.new(7,8,9)
139
+ a,b,c = x
140
+ assert(b == 8)
141
+
142
+ # to_ary will allow a struct to be treated like an array in
143
+ # passed parameters
144
+ myStruct = SuperStruct.new("alpha","beta","gamma")
145
+ x = myStruct.new(7,8,9)
146
+ b = meth(*x)
147
+
148
+ # to_hash will return a hash with fields as keys
149
+ myStruct = SuperStruct.new("alpha","beta","gamma")
150
+ x = myStruct.new(7,8,9)
151
+ h = x.to_hash
152
+ assert_equal({"alpha"=>7,"beta"=>8,"gamma"=>9},h)
153
+
154
+ # A field name (String) may be used in a hash-like notation
155
+ myStruct = SuperStruct.new("alpha","beta","gamma")
156
+ x = myStruct.new(7,8,9)
157
+ y = x["beta"]
158
+
159
+ # A field name (Symbol) may be used in a hash-like notation
160
+ myStruct = SuperStruct.new("alpha","beta","gamma")
161
+ x = myStruct.new(7,8,9)
162
+ y = x[:beta]
163
+
164
+ # [offset,length] may be used as for arrays
165
+ myStruct = SuperStruct.new("alpha","beta","gamma")
166
+ x = myStruct.new(7,8,9)
167
+ y = x[0,2]
168
+
169
+ # Ranges may be used as for arrays
170
+ myStruct = SuperStruct.new("alpha","beta","gamma")
171
+ x = myStruct.new(7,8,9)
172
+ y = x[1..2]
173
+
174
+ # Adding a field to an open struct adds it to the instance
175
+ myStruct = SuperStruct.open(:alpha)
176
+ x = myStruct.new
177
+ x.beta = 5
178
+
179
+ # Adding a field to an open struct adds it to the class also
180
+ myStruct = SuperStruct.open(:alpha)
181
+ x = myStruct.new
182
+ x.beta = 5
183
+
184
+ # An array passed to SuperStruct.new need not be starred
185
+ myStruct = SuperStruct.new(%w[alpha beta gamma])
186
+ x = myStruct.new
187
+
188
+ # A hash passed to #set will set multiple values at once
189
+ myStruct = SuperStruct.new(%w[alpha beta gamma])
190
+ x = myStruct.new
191
+ hash = {"alpha"=>234,"beta"=>345,"gamma"=>456}
192
+ x.set(hash)
193
+
194
+ # ||= works properly
195
+ x = SuperStruct.open.new
196
+ x.foo ||= 333
197
+ x.bar = x.bar || 444
198
+
199
+ # attr_tester will create a ?-method
200
+ myStruct = SuperStruct.new(:alive)
201
+ myStruct.attr_tester :alive
202
+ x = myStruct.new(true)
203
+ x.alive? # true
204
+
@@ -0,0 +1,213 @@
1
+ #
2
+ # SuperStruct
3
+ # Hal Fulton
4
+ # Version 1.0.0
5
+ # License: The Ruby License
6
+ #
7
+ # This is an easy way to create Struct-like classes; it converts easily
8
+ # between hashes and arrays, and it allows OpenStruct-like dynamic naming
9
+ # of members.
10
+ #
11
+ # Unlike Struct, it creates a "real" class, and it has real instance variables
12
+ # with predictable names.
13
+ #
14
+ # A basic limitation is that the hash keys must be legal method names (unless
15
+ # used with send()).
16
+ #
17
+ # Basically, ss["alpha"], ss[:alpha], ss[0], and ss.alpha all mean the same.
18
+ #
19
+
20
+
21
+ class SuperStruct
22
+
23
+ def SuperStruct.new(*args)
24
+ @table = []
25
+ @setsyms = [] # Setter symbols
26
+ klass = Class.new
27
+ if (args.size == 1) && (args[0].is_a? Array)
28
+ args = args[0]
29
+ end
30
+ strs = args.map {|x| x.to_s }
31
+ args.each_with_index do |k,i|
32
+ case
33
+ when (! [String,Symbol].include? k.class)
34
+ raise ArgumentError, "Need a String or Symbol"
35
+ when (strs[i] !~ /[_a-zA-Z][_a-zA-Z0-9]*/)
36
+ raise ArgumentError, "Illegal character"
37
+ end
38
+ k = k.intern if k.is_a? String
39
+ @table << k
40
+ @setsyms << (k.to_s + "=").intern
41
+ klass.instance_eval { attr_accessor k }
42
+ end
43
+
44
+ setsyms = @setsyms
45
+ table = @table
46
+ vals = @vals
47
+ klass.class_eval do
48
+ attr_reader :singleton
49
+ define_method(:initialize) do |*vals|
50
+ n = vals.size
51
+ m = table.size
52
+ case
53
+ when n < m
54
+ # raise ArgumentError, "Too few arguments (#{n} for #{m})"
55
+ # Never mind... extra variables will just be nil
56
+ when n > m
57
+ raise ArgumentError, "Too many arguments (#{n} for #{m})"
58
+ end
59
+ setsyms.each_with_index do |var,i|
60
+ self.send(var,vals[i])
61
+ end
62
+ end
63
+ define_method(:pretty_print) do |q| # pp.rb support
64
+ q.object_group(self) do
65
+ q.seplist(self.members, proc { q.text "," }) do |member|
66
+ # self.members.each do |member|
67
+ # q.text "," # unless q.first?
68
+ q.breakable
69
+ q.text member.to_s
70
+ q.text '='
71
+ q.group(1) do
72
+ q.breakable ''
73
+ q.pp self[member]
74
+ end
75
+ end
76
+ end
77
+ end
78
+ define_method(:inspect) do
79
+ str = "#<#{self.class}:"
80
+ table.each {|item| str << " #{item}=#{self.send(item)}" }
81
+ str + ">"
82
+ end
83
+ define_method(:[]) do |*index|
84
+ case index.map {|x| x.class }
85
+ when [Fixnum]
86
+ self.send(table[*index])
87
+ when [Fixnum,Fixnum], [Range]
88
+ table[*index].map {|x| self.send(x)}
89
+ when [String]
90
+ self.send(index[0].intern)
91
+ when [Symbol]
92
+ self.send(index[0])
93
+ else
94
+ raise ArgumentError,"Illegal index"
95
+ end
96
+ end
97
+ define_method(:[]=) do |*index|
98
+ value = index[-1]
99
+ index = index[0..-2]
100
+ case index.map {|x| x.class }
101
+ when [Fixnum]
102
+ self.send(table[*index])
103
+ when [Fixnum,Fixnum], [Range]
104
+ setsyms[*index].map {|x| self.send(x,value) }
105
+ when [String]
106
+ self.send(index[0].intern,value)
107
+ when [Symbol]
108
+ self.send(index[0],value)
109
+ else
110
+ raise ArgumentError,"Illegal index"
111
+ end
112
+ end
113
+ define_method(:to_a) { table.map {|x| eval("@"+x.to_s) } }
114
+ define_method(:to_ary) { to_a }
115
+ define_method(:members) { table.map {|x| x.to_s } }
116
+ define_method(:to_struct) do
117
+ mems = table
118
+ Struct.new("TEMP",*mems)
119
+ # Struct::TEMP.new(*vals) # Why doesn't this work??
120
+ data = mems.map {|x| self.send(x) }
121
+ Struct::TEMP.new(*data)
122
+ end
123
+ define_method(:to_hash) do
124
+ hash = {}
125
+ table.each do |mem|
126
+ mem = mem.to_s
127
+ hash.update(mem => self.send(mem))
128
+ end
129
+ hash
130
+ end
131
+ define_method(:set) {|h| h.each_pair {|k,v| send(k.to_s+"=",v) } }
132
+
133
+ # Class methods...
134
+
135
+ @singleton = class << self
136
+ self
137
+ end
138
+
139
+ @singleton.instance_eval do
140
+ define_method(:members) do
141
+ table.map {|x| x.to_s }
142
+ end
143
+ me = self
144
+ define_method(:attr_tester) do |*syms|
145
+ syms.each {|sym| alias_method(sym.to_s+"?",sym) }
146
+ end
147
+ end
148
+
149
+ end
150
+ klass
151
+ end
152
+
153
+
154
+ def SuperStruct.open(*args)
155
+ klass = SuperStruct.new(*args)
156
+ table = @table
157
+ setsyms = @setsyms
158
+ table = @table
159
+ klass.class_eval do
160
+ define_method(:method_missing) do |meth, *args|
161
+ mname = meth.id2name
162
+ if mname =~ /=$/
163
+ getter = mname.chop
164
+ setter = mname
165
+ elsif mname =~ /\?$/
166
+ raise NoMethodError # ?-methods are not created automatically
167
+ else
168
+ getter = mname
169
+ setter = mname + "="
170
+ end
171
+ gsym = getter.intern
172
+ ssym = setter.intern
173
+ ivar = "@" + getter
174
+ setsyms << setter
175
+ table << getter
176
+ len = args.length
177
+ if mname == getter
178
+ klass.class_eval do # getter
179
+ define_method(getter) do
180
+ instance_variable_get(ivar)
181
+ end
182
+ end
183
+ else
184
+ klass.class_eval do # setter
185
+ define_method(setter) do |*args|
186
+ if len != 1
187
+ raise ArgumentError, "Wrong # of arguments (#{len} for 1)",
188
+ caller(1)
189
+ end
190
+ instance_variable_set(ivar,args[0])
191
+ instance_variable_get(ivar)
192
+ end
193
+ end
194
+ end
195
+ if mname == setter
196
+ self.send(setter,*args)
197
+ else
198
+ if len == 0
199
+ self.send(getter)
200
+ else
201
+ raise NoMethodError, "Undefined method '#{mname}' for #{self}",
202
+ caller(1)
203
+ end
204
+ end
205
+ end
206
+ end
207
+ klass
208
+ end
209
+
210
+ end
211
+
212
+
213
+ require "test-sstruct" if $0 == __FILE__
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+
3
+ spec = Gem::Specification.new do |s|
4
+
5
+ #### Basic information.
6
+
7
+ s.name = 'sstruct'
8
+ s.version = "1.0.1"
9
+ s.summary = <<-EOF
10
+ SuperStruct class: Best of Struct, OpenStruct, Array, Hash, etc.
11
+ EOF
12
+ s.description = <<-EOF
13
+ The SuperStruct class allows the easy and quick creation of classes that
14
+ consist mainly of data. It borrows from Struct, OpenStruct, Array, Hash,
15
+ ArrayFields, and others.
16
+ EOF
17
+
18
+ #### Dependencies and requirements.
19
+
20
+ #### Which files are to be included in this gem? Everything! (Except CVS)
21
+
22
+ s.files = Dir.glob("**/*").delete_if { |item| item.include?("CVS") }
23
+
24
+ #### Load-time details: library and application (you will need one or both).
25
+
26
+ s.require_path = 'lib' # Use these for libraries.
27
+ s.autorequire = 'sstruct'
28
+
29
+ #### Documentation and testing.
30
+
31
+ s.has_rdoc = false
32
+ s.test_file = "test/test-sstruct.rb"
33
+
34
+ #### Author and project details.
35
+
36
+ s.author = "Hal E. Fulton"
37
+ s.email = "hal9000@hypermetrics.com"
38
+ s.homepage = "http://sstruct.rubyforge.org"
39
+ s.rubyforge_project = "sstruct"
40
+ end
@@ -0,0 +1,318 @@
1
+ #
2
+ # SuperStruct test code
3
+ # Hal Fulton
4
+ # Version 1.0.0 (in sync with library code)
5
+ # License: The Ruby License
6
+ #
7
+
8
+ require "test/unit"
9
+ require "sstruct"
10
+
11
+ class Tester < Test::Unit::TestCase
12
+
13
+ def test001
14
+ # Must pass in String or Symbol
15
+ assert_raises(ArgumentError) { SuperStruct.new(0) }
16
+ end
17
+
18
+ def test002
19
+ # Must pass in valid name(s)
20
+ assert_raises(ArgumentError) { SuperStruct.new("###") }
21
+ end
22
+
23
+ def test003
24
+ # Can't assign to nonexistent fields
25
+ myStruct = SuperStruct.new
26
+ assert_raises(ArgumentError) { myStruct.new(345) }
27
+ end
28
+
29
+ def test004
30
+ # Need not assign to existing fields (default to nil)
31
+ myStruct = SuperStruct.new(:alpha)
32
+ assert_nothing_raised(ArgumentError) { myStruct.new }
33
+ end
34
+
35
+ def test005
36
+ # A value assigned at construction may be retrieved
37
+ myStruct = SuperStruct.new(:alpha)
38
+ x = myStruct.new(234)
39
+ assert(x.alpha == 234)
40
+ end
41
+
42
+ def test006
43
+ # Unassigned fields are nil
44
+ myStruct = SuperStruct.new(:alpha,:beta)
45
+ x = myStruct.new(234)
46
+ assert(x.beta == nil)
47
+ end
48
+
49
+ def test007
50
+ # An open structure still may not construct with nonexistent fields
51
+ myStruct = SuperStruct.open
52
+ assert_raises(ArgumentError) { x = myStruct.new(234) }
53
+ end
54
+
55
+ def test008
56
+ # An open structure may assign fields not previously existing
57
+ myStruct = SuperStruct.open
58
+ x = myStruct.new
59
+ assert_nothing_raised { x.foobar = 123 }
60
+ end
61
+
62
+ def test009
63
+ # A field assigned to an open struct after its construction may be retrieved
64
+ myStruct = SuperStruct.open
65
+ x = myStruct.new
66
+ x.foobar = 123
67
+ assert(x.foobar == 123)
68
+ end
69
+
70
+ def test010
71
+ # The act of retrieving a nonexistent field from an open struct will
72
+ # create that field
73
+ myStruct = SuperStruct.open
74
+ x = myStruct.new
75
+ assert_nothing_raised { y = x.foobar }
76
+ end
77
+
78
+ def test011
79
+ # A field (in an open struct) that is unassigned will be nil
80
+ myStruct = SuperStruct.open
81
+ x = myStruct.new
82
+ y = x.foobar
83
+ assert(y == nil)
84
+ end
85
+
86
+ def test012
87
+ # A struct created with new rather than open cannot reference nonexistent
88
+ # fields
89
+ myStruct = SuperStruct.new
90
+ x = myStruct.new
91
+ assert_raises(NoMethodError) { y = x.foobar }
92
+ end
93
+
94
+ def test013
95
+ # Adding a field to a struct will create a writer and reader for that field
96
+ myStruct = SuperStruct.new(:alpha)
97
+ x = myStruct.new
98
+ x.send(:alpha=,1)
99
+ assert(x.alpha == 1)
100
+ end
101
+
102
+ def test014
103
+ # Only a single value may be passed to a writer (for code coverage)
104
+ myStruct = SuperStruct.new(:alpha)
105
+ x = myStruct.new
106
+ assert_raises(ArgumentError) { x.send(:alpha=,1,2) }
107
+ end
108
+
109
+ def test015
110
+ # An open struct will also create a writer and a reader together
111
+ myStruct = SuperStruct.open
112
+ x = myStruct.new
113
+ x.send(:alpha=,1)
114
+ assert(x.alpha == 1)
115
+ end
116
+
117
+ def test016
118
+ # Only a single value may be passed to a writer (for code coverage)
119
+ myStruct = SuperStruct.open
120
+ x = myStruct.new
121
+ assert_raises(ArgumentError) { x.send(:alpha=,1,2) }
122
+ end
123
+
124
+ def test017
125
+ # A field has a real writer and reader corresponding to it
126
+ myStruct = SuperStruct.new(:alpha)
127
+ x = myStruct.new
128
+ assert(myStruct.instance_methods.include?("alpha"))
129
+ assert(myStruct.instance_methods.include?("alpha="))
130
+ end
131
+
132
+ def test018
133
+ # Creating a field by retrieval in an open struct will NOT create a writer
134
+ # (This behavior has changed!)
135
+ myStruct = SuperStruct.open
136
+ x = myStruct.new
137
+ y = x.alpha
138
+ assert(myStruct.instance_methods.include?("alpha"))
139
+ assert(!myStruct.instance_methods.include?("alpha="))
140
+ end
141
+
142
+ def test019
143
+ # Creating a field by writing in an open struct will NOT create a reader
144
+ # (This behavior has changed!)
145
+ myStruct = SuperStruct.open
146
+ x = myStruct.new
147
+ x.alpha = 5
148
+ assert(myStruct.instance_methods.include?("alpha="))
149
+ assert(!myStruct.instance_methods.include?("alpha"))
150
+ end
151
+
152
+ def test020
153
+ # A string will work as well as a symbol
154
+ myStruct = SuperStruct.new("alpha")
155
+ x = myStruct.new
156
+ assert(myStruct.instance_methods.include?("alpha"))
157
+ assert(myStruct.instance_methods.include?("alpha="))
158
+ end
159
+
160
+ def test021
161
+ # to_a will return an array of values
162
+ myStruct = SuperStruct.new("alpha","beta","gamma")
163
+ x = myStruct.new(7,8,9)
164
+ assert(x.to_a == [7,8,9])
165
+ end
166
+
167
+ def test022
168
+ # Instance method 'members' will return a list of members (as strings)
169
+ myStruct = SuperStruct.new(:alpha,"beta")
170
+ x = myStruct.new
171
+ assert_equal(["alpha","beta"],x.members)
172
+ end
173
+
174
+ def test023
175
+ # Class method 'members' will return a list of members (as strings)
176
+ myStruct = SuperStruct.new(:alpha,"beta")
177
+ assert_equal(["alpha","beta"],myStruct.members)
178
+ end
179
+
180
+ def test024
181
+ # to_ary will allow a struct to be treated like an array in
182
+ # multiple assignment
183
+ myStruct = SuperStruct.new("alpha","beta","gamma")
184
+ x = myStruct.new(7,8,9)
185
+ a,b,c = x
186
+ assert(b == 8)
187
+ end
188
+
189
+ def aux025(*arr) # Just used in test 25
190
+ arr[1]
191
+ end
192
+
193
+ def test025
194
+ # to_ary will allow a struct to be treated like an array in
195
+ # passed parameters
196
+ myStruct = SuperStruct.new("alpha","beta","gamma")
197
+ x = myStruct.new(7,8,9)
198
+ b = aux025(*x)
199
+ assert(b == 8)
200
+ end
201
+
202
+ def test026
203
+ # to_hash will return a hash with fields as keys
204
+ myStruct = SuperStruct.new("alpha","beta","gamma")
205
+ x = myStruct.new(7,8,9)
206
+ h = x.to_hash
207
+ assert_equal({"alpha"=>7,"beta"=>8,"gamma"=>9},h)
208
+ end
209
+
210
+ def test027
211
+ # A field name (String) may be used in a hash-like notation
212
+ myStruct = SuperStruct.new("alpha","beta","gamma")
213
+ x = myStruct.new(7,8,9)
214
+ y = x["beta"]
215
+ assert(8,y)
216
+ end
217
+
218
+ def test028
219
+ # A field name (Symbol) may be used in a hash-like notation
220
+ myStruct = SuperStruct.new("alpha","beta","gamma")
221
+ x = myStruct.new(7,8,9)
222
+ y = x[:beta]
223
+ assert(8,y)
224
+ end
225
+
226
+ def test029
227
+ # [offset,length] may be used as for arrays
228
+ myStruct = SuperStruct.new("alpha","beta","gamma")
229
+ x = myStruct.new(7,8,9)
230
+ y = x[0,2]
231
+ assert([7,8],y)
232
+ end
233
+
234
+ def test030
235
+ # Ranges may be used as for arrays
236
+ myStruct = SuperStruct.new("alpha","beta","gamma")
237
+ x = myStruct.new(7,8,9)
238
+ y = x[1..2]
239
+ assert([8,9],y)
240
+ end
241
+
242
+ def test031
243
+ # Adding a field to an open struct adds it to the instance
244
+ myStruct = SuperStruct.open(:alpha)
245
+ x = myStruct.new
246
+ x.beta = 5
247
+ assert_equal(["alpha","beta"],x.members)
248
+ end
249
+
250
+ def test032
251
+ # Adding a field to an open struct adds it to the class also
252
+ myStruct = SuperStruct.open(:alpha)
253
+ x = myStruct.new
254
+ x.beta = 5
255
+ assert_equal(["alpha","beta"],myStruct.members)
256
+ end
257
+
258
+ def test033
259
+ # An array passed to SuperStruct.new need not be starred
260
+ myStruct = SuperStruct.new(%w[alpha beta gamma])
261
+ x = myStruct.new
262
+ assert_equal(%w[alpha beta gamma],x.members)
263
+ end
264
+
265
+ def xtest034
266
+ # A hash passed to SuperStruct.new will initialize the values
267
+ # (but order will not be predictable!)
268
+ assert false, "Not implemented yet."
269
+ end
270
+
271
+ def test035
272
+ # A hash passed to #set will set multiple values at once
273
+ myStruct = SuperStruct.new(%w[alpha beta gamma])
274
+ x = myStruct.new
275
+ hash = {"alpha"=>234,"beta"=>345,"gamma"=>456}
276
+ x.set(hash)
277
+ assert_equal([234,345,456], x.to_a)
278
+ end
279
+
280
+ def test036
281
+ # Make sure ||= works properly
282
+ x = SuperStruct.open.new
283
+ x.foo ||= 333
284
+ x.bar = x.bar || 444
285
+ assert_equal(333,x.foo)
286
+ assert_equal(444,x.bar)
287
+ end
288
+
289
+ def test037
290
+ # A simple array index works ok
291
+ myStruct = SuperStruct.new("alpha","beta","gamma")
292
+ x = myStruct.new(7,8,9)
293
+ assert_equal(7,x[0])
294
+ assert_equal(8,x[1])
295
+ assert_equal(9,x[2])
296
+ end
297
+
298
+ def test038
299
+ # attr_tester will create a ?-method
300
+ klass = SuperStruct.new(:alpha,:beta,:gamma)
301
+ klass.attr_tester :alpha, :gamma
302
+ x = klass.new(22,33,nil)
303
+ assert(x.alpha?)
304
+ assert_raises(NoMethodError) { x.beta? }
305
+ assert(! x.gamma?)
306
+ end
307
+
308
+ def test039
309
+ # attr_tester works with open() (?-methods not created)
310
+ klass = SuperStruct.open(:alpha,:beta,:gamma)
311
+ klass.attr_tester :alpha, :gamma
312
+ x = klass.new(22,33,nil)
313
+ assert(x.alpha?)
314
+ assert_raises(NoMethodError) { x.beta? } # ?-methods are not automatic
315
+ assert(! x.gamma?)
316
+ end
317
+
318
+ end
metadata ADDED
@@ -0,0 +1,43 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.1
3
+ specification_version: 1
4
+ name: sstruct
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.1
7
+ date: 2004-11-17
8
+ summary: "SuperStruct class: Best of Struct, OpenStruct, Array, Hash, etc."
9
+ require_paths:
10
+ - lib
11
+ author: Hal E. Fulton
12
+ email: hal9000@hypermetrics.com
13
+ homepage: http://sstruct.rubyforge.org
14
+ rubyforge_project: sstruct
15
+ description: "The SuperStruct class allows the easy and quick creation of classes that consist mainly of data. It borrows from Struct, OpenStruct, Array, Hash, ArrayFields, and others."
16
+ autorequire: sstruct
17
+ default_executable:
18
+ bindir: bin
19
+ has_rdoc: false
20
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
21
+ requirements:
22
+ -
23
+ - ">"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.0
26
+ version:
27
+ platform: ruby
28
+ files:
29
+ - doc
30
+ - sstruct.gemspec
31
+ - test
32
+ - lib
33
+ - doc/sstruct.txt
34
+ - test/test-sstruct.rb
35
+ - lib/sstruct.rb
36
+ test_files:
37
+ - test/test-sstruct.rb
38
+ rdoc_options: []
39
+ extra_rdoc_files: []
40
+ executables: []
41
+ extensions: []
42
+ requirements: []
43
+ dependencies: []