sstruct 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []