constructor 1.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/History.txt +3 -0
- data/Manifest.txt +6 -0
- data/README.txt +77 -0
- data/Rakefile +23 -0
- data/lib/constructor.rb +106 -0
- data/specs/constructor_spec.rb +319 -0
- metadata +62 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
constructor
|
2
|
+
|
3
|
+
* http://rubyforge.org/projects/atomicobjectrb/
|
4
|
+
* http://atomicobjectrb.rubyforge.org/constructor
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Declarative means to define object properties by passing a hash
|
9
|
+
to the constructor, which will set the corresponding ivars.
|
10
|
+
|
11
|
+
== FEATURES/PROBLEMS:
|
12
|
+
|
13
|
+
* Declarative constructor definition and ivar initialization
|
14
|
+
|
15
|
+
== SYNOPSIS:
|
16
|
+
|
17
|
+
require 'constructor'
|
18
|
+
|
19
|
+
class Horse
|
20
|
+
constructor :name, :breed, :weight
|
21
|
+
end
|
22
|
+
Horse.new :name => 'Ed', :breed => 'Mustang', :weight => 342
|
23
|
+
|
24
|
+
By default the ivars do not get accessors defined.
|
25
|
+
But you can get them auto-made if you want:
|
26
|
+
|
27
|
+
class Horse
|
28
|
+
constructor :name, :breed, :weight, :accessors => true
|
29
|
+
end
|
30
|
+
...
|
31
|
+
puts my_horse.weight
|
32
|
+
|
33
|
+
Arguments specified are required by default. You can disable
|
34
|
+
strict argument checking with :strict option. This means that
|
35
|
+
the constructor will not raise an error if you pass more or
|
36
|
+
fewer arguments than declared.
|
37
|
+
|
38
|
+
class Donkey
|
39
|
+
constructor :age, :odor, :strict => false
|
40
|
+
end
|
41
|
+
|
42
|
+
... this allows you to pass either an age or odor key (or neither)
|
43
|
+
to the Donkey constructor.
|
44
|
+
|
45
|
+
|
46
|
+
== REQUIREMENTS:
|
47
|
+
|
48
|
+
* rubygems
|
49
|
+
|
50
|
+
== INSTALL:
|
51
|
+
|
52
|
+
* sudo gem install constructor
|
53
|
+
|
54
|
+
== LICENSE:
|
55
|
+
|
56
|
+
(The MIT License)
|
57
|
+
|
58
|
+
Copyright (c) 2007 Atomic Object
|
59
|
+
|
60
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
61
|
+
a copy of this software and associated documentation files (the
|
62
|
+
'Software'), to deal in the Software without restriction, including
|
63
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
64
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
65
|
+
permit persons to whom the Software is furnished to do so, subject to
|
66
|
+
the following conditions:
|
67
|
+
|
68
|
+
The above copyright notice and this permission notice shall be
|
69
|
+
included in all copies or substantial portions of the Software.
|
70
|
+
|
71
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
72
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
73
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
74
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
75
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
76
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
77
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
require './lib/constructor.rb'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
|
7
|
+
desc 'Default: run specs'
|
8
|
+
task :default => :spec
|
9
|
+
Hoe.new('constructor', CONSTRUCTOR_VERSION) do |p|
|
10
|
+
p.rubyforge_name = 'atomicobjectrb'
|
11
|
+
p.author = 'Atomic Object'
|
12
|
+
p.email = 'dev@atomicobject.com'
|
13
|
+
p.summary = 'Declarative, named constructor arguments.'
|
14
|
+
p.description = p.paragraphs_of('README.txt', 2).join("\n\n")
|
15
|
+
p.url = p.paragraphs_of('README.txt', 1).first.gsub(/\* /,'').split(/\n/)
|
16
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Run constructor specs'
|
20
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
21
|
+
t.spec_files = FileList['specs/*_spec.rb']
|
22
|
+
t.spec_opts << '-c -f s'
|
23
|
+
end
|
data/lib/constructor.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
CONSTRUCTOR_VERSION = '1.0.0'
|
2
|
+
|
3
|
+
class Class
|
4
|
+
def constructor(*attrs)
|
5
|
+
# Look for embedded options in the listing:
|
6
|
+
opts = attrs.find { |a| a.kind_of?(Hash) and attrs.delete(a) }
|
7
|
+
do_acc = opts.nil? ? false : opts[:accessors] == true
|
8
|
+
require_args = opts.nil? ? true : opts[:strict] != false
|
9
|
+
super_args = opts.nil? ? nil : opts[:super]
|
10
|
+
|
11
|
+
# Incorporate superclass's constructor keys, if our superclass
|
12
|
+
if superclass.constructor_keys
|
13
|
+
attrs = [attrs,superclass.constructor_keys].flatten
|
14
|
+
end
|
15
|
+
# Generate ivar assigner code lines
|
16
|
+
assigns = ''
|
17
|
+
attrs.each do |k|
|
18
|
+
assigns += "@#{k.to_s} = args[:#{k.to_s}]\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
# If accessors option is on, declare accessors for the attributes:
|
22
|
+
if do_acc
|
23
|
+
self.class_eval "attr_accessor " + attrs.map {|x| ":#{x.to_s}"}.join(',')
|
24
|
+
end
|
25
|
+
|
26
|
+
# If user supplied super-constructor hints:
|
27
|
+
super_call = ''
|
28
|
+
if super_args
|
29
|
+
list = super_args.map do |a|
|
30
|
+
case a
|
31
|
+
when String
|
32
|
+
%|"#{a}"|
|
33
|
+
when Symbol
|
34
|
+
%|:#{a}|
|
35
|
+
end
|
36
|
+
end
|
37
|
+
super_call = %|super(#{list.join(',')})|
|
38
|
+
end
|
39
|
+
|
40
|
+
# If strict is on, define the constructor argument validator method,
|
41
|
+
# and setup the initializer to invoke the validator method.
|
42
|
+
# Otherwise, insert lax code into the initializer.
|
43
|
+
validation_code = "return if args.nil?"
|
44
|
+
if require_args
|
45
|
+
self.class_eval do
|
46
|
+
def _validate_constructor_args(args)
|
47
|
+
# First, make sure we've got args of some kind
|
48
|
+
unless args and args.keys and args.keys.size > 0
|
49
|
+
raise ConstructorArgumentError.new(self.class.constructor_keys)
|
50
|
+
end
|
51
|
+
# Scan for missing keys in the argument hash
|
52
|
+
a_keys = args.keys
|
53
|
+
missing = []
|
54
|
+
self.class.constructor_keys.each do |ck|
|
55
|
+
unless a_keys.member?(ck)
|
56
|
+
missing << ck
|
57
|
+
end
|
58
|
+
a_keys.delete(ck) # Delete inbound keys as we address them
|
59
|
+
end
|
60
|
+
if missing.size > 0 || a_keys.size > 0
|
61
|
+
raise ConstructorArgumentError.new(missing,a_keys)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
# Setup the code to insert into the initializer:
|
66
|
+
validation_code = "_validate_constructor_args args "
|
67
|
+
end
|
68
|
+
|
69
|
+
# Generate the initializer code
|
70
|
+
self.class_eval %{
|
71
|
+
def initialize(args=nil)
|
72
|
+
#{super_call}
|
73
|
+
#{validation_code}
|
74
|
+
#{assigns}
|
75
|
+
setup if respond_to?(:setup)
|
76
|
+
end
|
77
|
+
}
|
78
|
+
|
79
|
+
# Remember our constructor keys
|
80
|
+
@_ctor_keys = attrs
|
81
|
+
end
|
82
|
+
|
83
|
+
# Access the constructor keys for this class
|
84
|
+
def constructor_keys; @_ctor_keys; end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Fancy validation exception, based on missing and extraneous keys.
|
88
|
+
class ConstructorArgumentError < RuntimeError
|
89
|
+
def initialize(missing,rejected=[])
|
90
|
+
err_msg = ''
|
91
|
+
if missing.size > 0
|
92
|
+
err_msg = "Missing constructor args [#{missing.join(',')}]"
|
93
|
+
end
|
94
|
+
if rejected.size > 0
|
95
|
+
# Some inbound keys were not addressed earlier; this means they're unwanted
|
96
|
+
if err_msg
|
97
|
+
err_msg << "; " # Appending to earlier message about missing items
|
98
|
+
else
|
99
|
+
err_msg = ''
|
100
|
+
end
|
101
|
+
# Enumerate the rejected key names
|
102
|
+
err_msg << "Rejected constructor args [#{rejected.join(',')}]"
|
103
|
+
end
|
104
|
+
super err_msg
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/constructor')
|
2
|
+
|
3
|
+
class TestingClass
|
4
|
+
attr_accessor :foo, :bar, :why, :qux
|
5
|
+
constructor :foo, :bar, :why, :qux, :strict => false
|
6
|
+
|
7
|
+
def to_pretty_pretty
|
8
|
+
"#{@foo} #{@bar}"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
class Mama
|
14
|
+
attr_accessor :fat, :age
|
15
|
+
constructor :age, :strict => false
|
16
|
+
def setup
|
17
|
+
@fat = "much"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Baby < Mama
|
22
|
+
constructor :cuteness
|
23
|
+
end
|
24
|
+
|
25
|
+
class Sissy < Mama
|
26
|
+
attr_accessor :friends, :beauty
|
27
|
+
constructor :beauty, :strict => false
|
28
|
+
def setup
|
29
|
+
super #IMPORTANT!
|
30
|
+
@friends = "many"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TestingStrictArgsDefault
|
35
|
+
constructor :foo, :bar
|
36
|
+
def to_pretty_pretty
|
37
|
+
"#{@foo} #{@bar}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class TestingStrictArgs
|
42
|
+
constructor :foo, :bar, :strict => true
|
43
|
+
def to_pretty_pretty
|
44
|
+
"#{@foo} #{@bar}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class TestingStrictArgs2
|
49
|
+
constructor :foo, :bar, :accessors => true
|
50
|
+
end
|
51
|
+
|
52
|
+
class SubclassOfTestingClass < TestingClass
|
53
|
+
end
|
54
|
+
|
55
|
+
class SubclassOfTestingClass2 < TestingClass
|
56
|
+
def initialize; end
|
57
|
+
end
|
58
|
+
|
59
|
+
class SubclassOfTestingClass3 < TestingClass
|
60
|
+
attr_reader :my_new_var
|
61
|
+
def initialize(hash = nil)
|
62
|
+
super
|
63
|
+
@my_new_var = "something"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class TestingAutoAccessors
|
68
|
+
constructor :foo, :bar, :why, :qux, :accessors => true, :strict => false
|
69
|
+
def to_pretty_pretty
|
70
|
+
"#{@foo} #{@bar}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class TestingSuperConstructorBase
|
75
|
+
attr_reader :a, :b
|
76
|
+
def initialize(a,b)
|
77
|
+
@a = a
|
78
|
+
@b = b
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class TestingSuperConstructor < TestingSuperConstructorBase
|
83
|
+
constructor :far, :away, :accessors => true, :super => ["once", :twice], :strict => false
|
84
|
+
end
|
85
|
+
|
86
|
+
class TestingSuperConstructorBase2
|
87
|
+
attr_reader :c, :d
|
88
|
+
def initialize
|
89
|
+
@c = 'what a'
|
90
|
+
@d = 'day for'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class TestingSuperConstructor2 < TestingSuperConstructorBase2
|
95
|
+
constructor :some, :accessors => true, :super => [], :strict => false
|
96
|
+
end
|
97
|
+
|
98
|
+
class TestingBlockedAccessors
|
99
|
+
constructor :foo, :bar, :accessors => false
|
100
|
+
def to_pretty_pretty
|
101
|
+
"#{@foo} #{@bar}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Papa
|
106
|
+
constructor :car, :saw
|
107
|
+
end
|
108
|
+
|
109
|
+
class Sonny < Papa
|
110
|
+
constructor :computer, :accessors => true
|
111
|
+
end
|
112
|
+
|
113
|
+
class Llamma
|
114
|
+
attr_accessor :hungry, :hair
|
115
|
+
constructor :hair
|
116
|
+
def setup
|
117
|
+
@hungry = true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'standard constructor usage' do
|
122
|
+
it 'allows for object construction using a hash of named arguments' do
|
123
|
+
fuh = TestingClass.new(
|
124
|
+
:foo => 'my foo',
|
125
|
+
:bar => 'my bar',
|
126
|
+
:qux => 'my qux',
|
127
|
+
:why => 'lucky'
|
128
|
+
)
|
129
|
+
|
130
|
+
fuh.foo.should eql('my foo')
|
131
|
+
fuh.bar.should eql('my bar')
|
132
|
+
fuh.qux.should eql('my qux')
|
133
|
+
fuh.why.should eql('lucky')
|
134
|
+
fuh.to_pretty_pretty.should eql('my foo my bar')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'calls setup method if defined' do
|
138
|
+
ralph = Llamma.new :hair => 'red'
|
139
|
+
ralph.hungry.should be_true
|
140
|
+
ralph.hair.should eql('red')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "constructor's accessor option" do
|
145
|
+
it 'provides accessors for constructor arguments when accessor option is true' do
|
146
|
+
fuh = TestingAutoAccessors.new(
|
147
|
+
:foo => 'my foo',
|
148
|
+
:bar => 'my bar',
|
149
|
+
:qux => 'my qux',
|
150
|
+
:why => 'lucky'
|
151
|
+
)
|
152
|
+
fuh.foo.should eql('my foo')
|
153
|
+
fuh.bar.should eql('my bar')
|
154
|
+
fuh.qux.should eql('my qux')
|
155
|
+
fuh.why.should eql('lucky')
|
156
|
+
fuh.to_pretty_pretty.should eql('my foo my bar')
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'does not provide accessors for constructor arguments when accessor option is false' do
|
160
|
+
fuh = TestingBlockedAccessors.new :foo => 'my foo', :bar => 'my bar'
|
161
|
+
lambda {fuh.foo}.should raise_error(NoMethodError)
|
162
|
+
lambda {fuh.bar}.should raise_error(NoMethodError)
|
163
|
+
fuh.to_pretty_pretty.should eql('my foo my bar')
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'using constructor with inheritance' do
|
168
|
+
it 'allows for inheritance of constructor arguments using a non-constructor defined subclass' do
|
169
|
+
fuh = SubclassOfTestingClass.new :foo => 'whu?'
|
170
|
+
fuh.foo.should eql('whu?')
|
171
|
+
fuh.bar.should be_nil
|
172
|
+
fuh.qux.should be_nil
|
173
|
+
fuh.why.should be_nil
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'allows for standard construction of a non-constructor subclass of a non-strict constuctor superclass' do
|
177
|
+
fuh = SubclassOfTestingClass2.new
|
178
|
+
fuh.foo.should be_nil
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'runs initialize method of a sublcass' do
|
182
|
+
fuh = SubclassOfTestingClass3.new
|
183
|
+
fuh.my_new_var.should eql('something')
|
184
|
+
fuh.foo.should be_nil
|
185
|
+
fuh.bar.should be_nil
|
186
|
+
fuh.qux.should be_nil
|
187
|
+
fuh.why.should be_nil
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'passes named constructor args to superclass when subclass calls super' do
|
191
|
+
fuh = SubclassOfTestingClass3.new :foo => 12
|
192
|
+
fuh.my_new_var.should eql('something')
|
193
|
+
fuh.foo.should eql(12)
|
194
|
+
fuh.bar.should be_nil
|
195
|
+
fuh.qux.should be_nil
|
196
|
+
fuh.why.should be_nil
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'allows for inheritance of constructor arguments using a constructor defined subclass' do
|
200
|
+
s = Sonny.new :car => 'Nissan', :saw => 'Dewalt', :computer => 'Dell'
|
201
|
+
s.computer.should eql('Dell')
|
202
|
+
s.saw.should eql('Dewalt')
|
203
|
+
s.car.should eql('Nissan')
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'calls the setup method on superclass if subclass does not define a setup method' do
|
207
|
+
baby = Baby.new :cuteness => 'little', :age => 1
|
208
|
+
baby.fat.should eql('much')
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'calls parent class setup when super is called from subclass setup' do
|
212
|
+
m = Mama.new :age => 55
|
213
|
+
m.age.should eql(55)
|
214
|
+
m.fat.should eql('much')
|
215
|
+
|
216
|
+
s = Sissy.new :age => 19, :beauty => 'medium', :fat => 'yeah'
|
217
|
+
s.age.should eql(19)
|
218
|
+
s.beauty.should eql('medium')
|
219
|
+
s.fat.should eql('much')
|
220
|
+
s.friends.should eql('many')
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'passes arguments given in the super option to the initializer of a non-constructor defined superclass' do
|
224
|
+
tsc = TestingSuperConstructor.new(:far => 'oo', :away => 'kk')
|
225
|
+
tsc.far.should eql('oo')
|
226
|
+
tsc.away.should eql('kk')
|
227
|
+
tsc.a.should eql("once")
|
228
|
+
tsc.b.should eql(:twice)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'calls non-constructor defined superclass constructor when the super option is an empty array' do
|
232
|
+
tsc = TestingSuperConstructor2.new(:some => 'thing')
|
233
|
+
tsc.some.should eql('thing')
|
234
|
+
tsc.c.should eql('what a')
|
235
|
+
tsc.d.should eql('day for')
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'stict mode usage' do
|
240
|
+
it 'allows omission of arguments when strict is off' do
|
241
|
+
fuh = TestingClass.new :foo => 'my foo'
|
242
|
+
|
243
|
+
fuh.foo.should eql('my foo')
|
244
|
+
fuh.bar.should be_nil
|
245
|
+
fuh.qux.should be_nil
|
246
|
+
fuh.why.should be_nil
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'allows no arguments to a constructor when strict is off' do
|
250
|
+
fuh = TestingClass.new
|
251
|
+
fuh.foo.should be_nil
|
252
|
+
fuh.bar.should be_nil
|
253
|
+
fuh.qux.should be_nil
|
254
|
+
fuh.why.should be_nil
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'does not interfere with normal object construction' do
|
258
|
+
require 'rexml/document'
|
259
|
+
d = REXML::Document.new '<base/>'
|
260
|
+
d.should_not be_nil
|
261
|
+
d.root.name.should eql('base')
|
262
|
+
end
|
263
|
+
|
264
|
+
def see_strict_args_in_effect_for(clazz)
|
265
|
+
fuh = clazz.new :foo => 'my foo', :bar => 'my bar'
|
266
|
+
fuh.to_pretty_pretty.should eql('my foo my bar')
|
267
|
+
|
268
|
+
# Omit foo
|
269
|
+
lambda {
|
270
|
+
TestingStrictArgsDefault.new :bar => 'ok,yeah'
|
271
|
+
}.should raise_error(ConstructorArgumentError, /foo/)
|
272
|
+
|
273
|
+
# Omit bar
|
274
|
+
lambda {
|
275
|
+
TestingStrictArgsDefault.new :foo => 'ok,yeah'
|
276
|
+
}.should raise_error(ConstructorArgumentError, /bar/)
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'defaults to strict argument enforcement' do
|
280
|
+
see_strict_args_in_effect_for TestingStrictArgsDefault
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'enforces strict arguments when strict option is true' do
|
284
|
+
see_strict_args_in_effect_for TestingStrictArgs
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'does not allow empty constructor arguments when strict option is true' do
|
288
|
+
lambda {TestingStrictArgs.new {}}.should raise_error(ConstructorArgumentError,/foo,bar/)
|
289
|
+
lambda {TestingStrictArgs.new}.should raise_error(ConstructorArgumentError,/foo,bar/)
|
290
|
+
lambda {TestingStrictArgs.new nil}.should raise_error(ConstructorArgumentError,/foo,bar/)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'does not allow extraneous arguments when strict option is true' do
|
294
|
+
lambda {
|
295
|
+
TestingStrictArgs.new :foo => 1, :bar => 2, :other => 3, :thing => 4
|
296
|
+
}.should raise_error(ConstructorArgumentError,/thing,other/)
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'allows for setting accessors option while in strict mode' do
|
300
|
+
t2 = TestingStrictArgs2.new :foo => 1, :bar => 2
|
301
|
+
|
302
|
+
# See that accessors work
|
303
|
+
t2.foo.should eql(1)
|
304
|
+
t2.bar.should eql(2)
|
305
|
+
|
306
|
+
# See that strictness still applies
|
307
|
+
lambda {TestingStrictArgs2.new :no => 'good'}.should raise_error(ConstructorArgumentError)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe 'catching ConstructorArgumentError' do
|
312
|
+
it 'allows for generic rescuing of constructor argument errors' do
|
313
|
+
begin
|
314
|
+
TestingStrictArgs.new :broken => 'yoobetcha'
|
315
|
+
rescue => bad_news
|
316
|
+
bad_news.should be_kind_of(ConstructorArgumentError)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: constructor
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-11-18 00:00:00 -05:00
|
8
|
+
summary: Declarative, named constructor arguments.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: dev@atomicobject.com
|
12
|
+
homepage: http://rubyforge.org/projects/atomicobjectrb/
|
13
|
+
rubyforge_project: atomicobjectrb
|
14
|
+
description: "== DESCRIPTION: Declarative means to define object properties by passing a hash to the constructor, which will set the corresponding ivars."
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Atomic Object
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- Rakefile
|
36
|
+
- lib/constructor.rb
|
37
|
+
- specs/constructor_spec.rb
|
38
|
+
test_files: []
|
39
|
+
|
40
|
+
rdoc_options:
|
41
|
+
- --main
|
42
|
+
- README.txt
|
43
|
+
extra_rdoc_files:
|
44
|
+
- History.txt
|
45
|
+
- Manifest.txt
|
46
|
+
- README.txt
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
requirements: []
|
52
|
+
|
53
|
+
dependencies:
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: hoe
|
56
|
+
version_requirement:
|
57
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.0
|
62
|
+
version:
|