dry-validation 0.9.5 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -8
- data/CHANGELOG.md +34 -1
- data/Gemfile +2 -0
- data/Rakefile +12 -3
- data/config/errors.yml +1 -0
- data/dry-validation.gemspec +3 -2
- data/lib/dry/validation/executor.rb +3 -27
- data/lib/dry/validation/extensions/monads.rb +17 -0
- data/lib/dry/validation/extensions/struct.rb +32 -0
- data/lib/dry/validation/extensions.rb +7 -0
- data/lib/dry/validation/input_processor_compiler.rb +19 -3
- data/lib/dry/validation/message.rb +43 -30
- data/lib/dry/validation/message_compiler/visitor_opts.rb +39 -0
- data/lib/dry/validation/message_compiler.rb +98 -52
- data/lib/dry/validation/message_set.rb +59 -30
- data/lib/dry/validation/predicate_registry.rb +17 -6
- data/lib/dry/validation/result.rb +39 -17
- data/lib/dry/validation/schema/check.rb +5 -4
- data/lib/dry/validation/schema/class_interface.rb +6 -13
- data/lib/dry/validation/schema/dsl.rb +9 -3
- data/lib/dry/validation/schema/form.rb +12 -3
- data/lib/dry/validation/schema/json.rb +12 -3
- data/lib/dry/validation/schema/key.rb +6 -6
- data/lib/dry/validation/schema/rule.rb +14 -8
- data/lib/dry/validation/schema/value.rb +23 -21
- data/lib/dry/validation/schema.rb +9 -12
- data/lib/dry/validation/schema_compiler.rb +16 -2
- data/lib/dry/validation/version.rb +1 -1
- data/lib/dry/validation.rb +11 -23
- data/spec/extensions/monads/result_spec.rb +38 -0
- data/spec/extensions/struct/schema_spec.rb +32 -0
- data/spec/integration/custom_predicates_spec.rb +7 -6
- data/spec/integration/form/predicates/size/fixed_spec.rb +0 -2
- data/spec/integration/form/predicates/size/range_spec.rb +0 -2
- data/spec/integration/hints_spec.rb +2 -6
- data/spec/integration/json/defining_base_schema_spec.rb +41 -0
- data/spec/integration/{error_compiler_spec.rb → message_compiler_spec.rb} +79 -131
- data/spec/integration/result_spec.rb +26 -4
- data/spec/integration/schema/check_with_nested_el_spec.rb +1 -1
- data/spec/integration/schema/check_with_nth_el_spec.rb +1 -1
- data/spec/integration/schema/defining_base_schema_spec.rb +3 -0
- data/spec/integration/schema/dynamic_predicate_args_spec.rb +34 -9
- data/spec/integration/schema/form/defining_base_schema_spec.rb +41 -0
- data/spec/integration/schema/json_spec.rb +1 -0
- data/spec/integration/schema/macros/input_spec.rb +26 -0
- data/spec/integration/schema/macros/rule_spec.rb +2 -1
- data/spec/integration/schema/macros/value_spec.rb +1 -1
- data/spec/integration/schema/macros/when_spec.rb +1 -24
- data/spec/integration/schema/or_spec.rb +87 -0
- data/spec/integration/schema/predicates/custom_spec.rb +4 -4
- data/spec/integration/schema/predicates/even_spec.rb +10 -10
- data/spec/integration/schema/predicates/odd_spec.rb +10 -10
- data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -3
- data/spec/integration/schema/predicates/size/range_spec.rb +0 -2
- data/spec/integration/schema/predicates/type_spec.rb +22 -0
- data/spec/integration/schema/using_types_spec.rb +14 -41
- data/spec/integration/schema/validate_spec.rb +83 -0
- data/spec/integration/schema/xor_spec.rb +5 -5
- data/spec/integration/schema_builders_spec.rb +4 -2
- data/spec/integration/schema_spec.rb +8 -0
- data/spec/shared/message_compiler.rb +11 -0
- data/spec/shared/predicate_helper.rb +5 -3
- data/spec/spec_helper.rb +15 -0
- data/spec/unit/input_processor_compiler/form_spec.rb +3 -3
- data/spec/unit/message_compiler/visit_failure_spec.rb +38 -0
- data/spec/unit/message_compiler/visit_spec.rb +16 -0
- data/spec/unit/message_compiler_spec.rb +7 -0
- data/spec/unit/predicate_registry_spec.rb +2 -2
- data/spec/unit/schema/key_spec.rb +19 -12
- data/spec/unit/schema/rule_spec.rb +14 -6
- data/spec/unit/schema/value_spec.rb +49 -52
- metadata +50 -20
- data/lib/dry/validation/constants.rb +0 -6
- data/lib/dry/validation/error.rb +0 -26
- data/lib/dry/validation/error_compiler.rb +0 -81
- data/lib/dry/validation/hint_compiler.rb +0 -104
- data/spec/unit/error_compiler_spec.rb +0 -7
- data/spec/unit/hint_compiler_spec.rb +0 -51
@@ -1,7 +1,7 @@
|
|
1
1
|
RSpec.describe 'Predicates: even' do
|
2
2
|
context 'with required' do
|
3
3
|
subject(:schema) do
|
4
|
-
Dry::Validation.
|
4
|
+
Dry::Validation.Schema do
|
5
5
|
required(:foo) { odd? }
|
6
6
|
end
|
7
7
|
end
|
@@ -57,7 +57,7 @@ RSpec.describe 'Predicates: even' do
|
|
57
57
|
|
58
58
|
context 'with optional' do
|
59
59
|
subject(:schema) do
|
60
|
-
Dry::Validation.
|
60
|
+
Dry::Validation.Schema do
|
61
61
|
optional(:foo) { odd? }
|
62
62
|
end
|
63
63
|
end
|
@@ -115,7 +115,7 @@ RSpec.describe 'Predicates: even' do
|
|
115
115
|
context 'with required' do
|
116
116
|
context 'with value' do
|
117
117
|
subject(:schema) do
|
118
|
-
Dry::Validation.
|
118
|
+
Dry::Validation.Schema do
|
119
119
|
required(:foo).value(:odd?)
|
120
120
|
end
|
121
121
|
end
|
@@ -171,7 +171,7 @@ RSpec.describe 'Predicates: even' do
|
|
171
171
|
|
172
172
|
context 'with filled' do
|
173
173
|
subject(:schema) do
|
174
|
-
Dry::Validation.
|
174
|
+
Dry::Validation.Schema do
|
175
175
|
required(:foo).filled(:odd?)
|
176
176
|
end
|
177
177
|
end
|
@@ -227,7 +227,7 @@ RSpec.describe 'Predicates: even' do
|
|
227
227
|
|
228
228
|
context 'with maybe' do
|
229
229
|
subject(:schema) do
|
230
|
-
Dry::Validation.
|
230
|
+
Dry::Validation.Schema do
|
231
231
|
required(:foo).maybe(:odd?)
|
232
232
|
end
|
233
233
|
end
|
@@ -260,7 +260,7 @@ RSpec.describe 'Predicates: even' do
|
|
260
260
|
let(:input) { { foo: '' } }
|
261
261
|
|
262
262
|
it 'is successful' do
|
263
|
-
expect
|
263
|
+
expect { result }.to raise_error(NoMethodError)
|
264
264
|
end
|
265
265
|
end
|
266
266
|
|
@@ -285,7 +285,7 @@ RSpec.describe 'Predicates: even' do
|
|
285
285
|
context 'with optional' do
|
286
286
|
context 'with value' do
|
287
287
|
subject(:schema) do
|
288
|
-
Dry::Validation.
|
288
|
+
Dry::Validation.Schema do
|
289
289
|
optional(:foo).value(:odd?)
|
290
290
|
end
|
291
291
|
end
|
@@ -341,7 +341,7 @@ RSpec.describe 'Predicates: even' do
|
|
341
341
|
|
342
342
|
context 'with filled' do
|
343
343
|
subject(:schema) do
|
344
|
-
Dry::Validation.
|
344
|
+
Dry::Validation.Schema do
|
345
345
|
optional(:foo).filled(:odd?)
|
346
346
|
end
|
347
347
|
end
|
@@ -397,7 +397,7 @@ RSpec.describe 'Predicates: even' do
|
|
397
397
|
|
398
398
|
context 'with maybe' do
|
399
399
|
subject(:schema) do
|
400
|
-
Dry::Validation.
|
400
|
+
Dry::Validation.Schema do
|
401
401
|
optional(:foo).maybe(:odd?)
|
402
402
|
end
|
403
403
|
end
|
@@ -430,7 +430,7 @@ RSpec.describe 'Predicates: even' do
|
|
430
430
|
let(:input) { { foo: '' } }
|
431
431
|
|
432
432
|
it 'is successful' do
|
433
|
-
expect
|
433
|
+
expect { result }.to raise_error(NoMethodError)
|
434
434
|
end
|
435
435
|
end
|
436
436
|
|
@@ -34,7 +34,6 @@ RSpec.describe 'Predicates: Size' do
|
|
34
34
|
context 'with blank input' do
|
35
35
|
let(:input) { { foo: '' } }
|
36
36
|
|
37
|
-
#see: https://github.com/dry-rb/dry-validation/issues/121
|
38
37
|
it 'is not successful' do
|
39
38
|
expect(result).to be_failing ['length must be 3']
|
40
39
|
end
|
@@ -184,7 +183,6 @@ RSpec.describe 'Predicates: Size' do
|
|
184
183
|
let(:input) { { foo: '' } }
|
185
184
|
|
186
185
|
it 'is not successful' do
|
187
|
-
pending
|
188
186
|
expect(result).to be_failing ['must be filled', 'length must be 3']
|
189
187
|
end
|
190
188
|
end
|
@@ -333,7 +331,6 @@ RSpec.describe 'Predicates: Size' do
|
|
333
331
|
let(:input) { { foo: '' } }
|
334
332
|
|
335
333
|
it 'is not successful' do
|
336
|
-
pending
|
337
334
|
expect(result).to be_failing ['must be filled', 'length must be 3']
|
338
335
|
end
|
339
336
|
end
|
@@ -181,7 +181,6 @@ RSpec.describe 'Predicates: Size' do
|
|
181
181
|
let(:input) { { foo: '' } }
|
182
182
|
|
183
183
|
it 'is not successful' do
|
184
|
-
pending
|
185
184
|
expect(result).to be_failing ['must be filled', 'length must be within 2 - 3']
|
186
185
|
end
|
187
186
|
end
|
@@ -329,7 +328,6 @@ RSpec.describe 'Predicates: Size' do
|
|
329
328
|
let(:input) { { foo: '' } }
|
330
329
|
|
331
330
|
it 'is not successful' do
|
332
|
-
pending
|
333
331
|
expect(result).to be_failing ['must be filled', 'length must be within 2 - 3']
|
334
332
|
end
|
335
333
|
end
|
@@ -388,4 +388,26 @@ RSpec.describe 'Predicates: Type' do
|
|
388
388
|
end
|
389
389
|
end
|
390
390
|
end
|
391
|
+
|
392
|
+
context 'with a custom class' do
|
393
|
+
subject(:schema) do
|
394
|
+
Dry::Validation.Schema do
|
395
|
+
required(:foo).value(type?: CustomClass)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
around do |example|
|
400
|
+
CustomClass = Class.new
|
401
|
+
example.run
|
402
|
+
Object.send(:remove_const, :CustomClass)
|
403
|
+
end
|
404
|
+
|
405
|
+
it 'it succeeds with valid input' do
|
406
|
+
expect(schema.(foo: CustomClass.new)).to be_success
|
407
|
+
end
|
408
|
+
|
409
|
+
it 'it fails with invalid input' do
|
410
|
+
expect(schema.(foo: 'oops')).to be_failing ["must be #{CustomClass}"]
|
411
|
+
end
|
412
|
+
end
|
391
413
|
end
|
@@ -23,58 +23,31 @@ RSpec.describe Dry::Validation::Schema, 'defining schema using dry types' do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'passes when input is valid' do
|
26
|
-
expect(schema.(email: 'jane@doe', age: 19, country: 'Australia')).to be_success
|
27
|
-
expect(schema.(email: 'jane@doe', age: nil, country: 'Poland')).to be_success
|
26
|
+
expect(schema.call(email: 'jane@doe', age: 19, country: 'Australia')).to be_success
|
27
|
+
expect(schema.call(email: 'jane@doe', age: nil, country: 'Poland')).to be_success
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'fails when input is not valid' do
|
31
|
-
expect(schema.(email: '', age: 19, country: 'New Zealand')).to_not be_success
|
32
|
-
expect(schema.(email: 'jane@doe', age: 17)).to_not be_success
|
33
|
-
expect(schema.(email: 'jane@doe', age: '19')).to_not be_success
|
31
|
+
expect(schema.call(email: '', age: 19, country: 'New Zealand')).to_not be_success
|
32
|
+
expect(schema.call(email: 'jane@doe', age: 17)).to_not be_success
|
33
|
+
expect(schema.call(email: 'jane@doe', age: '19')).to_not be_success
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'correctly responds to messages' do
|
37
|
-
expect(schema.({}).messages).to eq(
|
38
|
-
age: [
|
39
|
-
country: [
|
40
|
-
email: [
|
37
|
+
expect(schema.call({}).messages).to eq(
|
38
|
+
age: ['is missing', 'must be Integer', 'must be greater than 18'],
|
39
|
+
country: ['is missing', 'must be String', 'must be one of: Australia, Poland'],
|
40
|
+
email: ['is missing', 'must be String']
|
41
41
|
)
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'fails when sum-type rule did not pass' do
|
45
|
-
result = schema.(email: 'jane@doe', age: 19, country: 'Australia', admin: 'foo')
|
45
|
+
result = schema.call(email: 'jane@doe', age: 19, country: 'Australia', admin: 'foo')
|
46
46
|
expect(result.messages).to eql(
|
47
|
-
admin: ['must be
|
47
|
+
admin: ['must be TrueClass or must be FalseClass']
|
48
48
|
)
|
49
49
|
end
|
50
50
|
|
51
|
-
context "structs" do
|
52
|
-
subject(:schema) do
|
53
|
-
Dry::Validation.Schema do
|
54
|
-
required(:person).filled(Person)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class Name < Dry::Types::Value
|
59
|
-
attribute :given_name, Dry::Types['strict.string']
|
60
|
-
attribute :family_name, Dry::Types['strict.string']
|
61
|
-
end
|
62
|
-
|
63
|
-
class Person < Dry::Types::Value
|
64
|
-
attribute :name, Name
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'handles nested structs' do
|
68
|
-
expect(schema.(person: { name: { given_name: 'Tim', family_name: 'Cooper' } })).to be_success
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'fails when input is not valid' do
|
72
|
-
expect(schema.(person: {name: {given_name: 'Tim'}}).messages).to eq(
|
73
|
-
person: { name: { family_name: ["is missing"] } }
|
74
|
-
)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
51
|
context 'custom coercions' do
|
79
52
|
subject(:schema) do
|
80
53
|
Dry::Validation.Schema do
|
@@ -85,7 +58,7 @@ RSpec.describe Dry::Validation::Schema, 'defining schema using dry types' do
|
|
85
58
|
end
|
86
59
|
|
87
60
|
it 'applies custom types to input prior validation' do
|
88
|
-
result = schema.(email: ' jane@doe.org ')
|
61
|
+
result = schema.call(email: ' jane@doe.org ')
|
89
62
|
|
90
63
|
expect(result).to be_success
|
91
64
|
expect(result.to_h).to eql(email: 'jane@doe.org')
|
@@ -102,7 +75,7 @@ RSpec.describe Dry::Validation::Schema, 'defining schema using dry types' do
|
|
102
75
|
end
|
103
76
|
|
104
77
|
it 'applies custom types to input prior validation' do
|
105
|
-
result = schema.(quantity: '2', percentage: '0.5', switch: '0')
|
78
|
+
result = schema.call(quantity: '2', percentage: '0.5', switch: '0')
|
106
79
|
|
107
80
|
expect(result).to be_success
|
108
81
|
expect(result.to_h).to eql(quantity: 2, percentage: BigDecimal('0.5'), switch: false)
|
@@ -117,7 +90,7 @@ RSpec.describe Dry::Validation::Schema, 'defining schema using dry types' do
|
|
117
90
|
end
|
118
91
|
|
119
92
|
it 'applies type constraint checks to each element' do
|
120
|
-
result = schema.(countries:
|
93
|
+
result = schema.call(countries: %w(Poland Australia))
|
121
94
|
|
122
95
|
expect(result).to be_success
|
123
96
|
expect(result.to_h).to eql(countries: %w(Poland Australia))
|
@@ -0,0 +1,83 @@
|
|
1
|
+
RSpec.describe Dry::Validation::Schema, 'arbitrary validation blocks' do
|
2
|
+
context 'with a single value' do
|
3
|
+
subject(:schema) do
|
4
|
+
Dry::Validation.Schema do
|
5
|
+
configure do
|
6
|
+
option :email_regex, /@/
|
7
|
+
|
8
|
+
def self.messages
|
9
|
+
super.merge(en: { errors: { email?: '%{value} looks like an invalid email' } })
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
required(:email).filled
|
14
|
+
|
15
|
+
validate(email?: :email) do |value|
|
16
|
+
email_regex.match(value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns success for valid input' do
|
22
|
+
expect(schema.(email: 'jane@doe.org')).to be_success
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns failure for invalid input' do
|
26
|
+
expect(schema.(email: 'jane')).to be_failure
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'adds correct error message' do
|
30
|
+
expect(schema.(email: 'jane').messages).to eql(
|
31
|
+
email: ['jane looks like an invalid email']
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is not executed when deps are invalid' do
|
36
|
+
expect(schema.(email: nil)).to be_failure
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with more than one value' do
|
41
|
+
subject(:schema) do
|
42
|
+
Dry::Validation.Schema do
|
43
|
+
configure do
|
44
|
+
def self.messages
|
45
|
+
super.merge(en: { errors: { email_required: 'provide email' }})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
required(:email).maybe(:str?)
|
50
|
+
required(:newsletter).value(:bool?)
|
51
|
+
|
52
|
+
validate(email_required: %i[newsletter email]) do |newsletter, email|
|
53
|
+
if newsletter == true
|
54
|
+
!email.nil?
|
55
|
+
else
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns success for valid input' do
|
63
|
+
expect(schema.(newsletter: false, email: nil)).to be_success
|
64
|
+
expect(schema.(newsletter: true, email: 'jane@doe.org')).to be_success
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns failure for invalid input' do
|
68
|
+
expect(schema.(newsletter: true, email: nil)).to be_failure
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'adds correct error message' do
|
72
|
+
expect(schema.(newsletter: true, email: nil).errors).to eql(
|
73
|
+
email_required: ['provide email']
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'is not executed when deps are invalid' do
|
78
|
+
expect(schema.(newsletter: 'oops', email: '').errors).to eql(
|
79
|
+
newsletter: ['must be boolean']
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -13,8 +13,8 @@ RSpec.describe 'Schema with xor rules' do
|
|
13
13
|
|
14
14
|
required(:have_cake).filled
|
15
15
|
|
16
|
-
rule(:
|
17
|
-
|
16
|
+
rule(be_reasonable: %i[eat_cake have_cake]) do |ec, hc|
|
17
|
+
ec.eql?('yes!') ^ hc.eql?('yes!')
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -27,9 +27,9 @@ RSpec.describe 'Schema with xor rules' do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'fails when both options are selected' do
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
expect(schema.(eat_cake: 'yes!', have_cake: 'yes!').messages).to eql(
|
31
|
+
be_reasonable: ['you cannot eat cake and have cake!']
|
32
|
+
)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -4,12 +4,14 @@ RSpec.describe 'Building schemas' do
|
|
4
4
|
predicates = Module.new do
|
5
5
|
include Dry::Logic::Predicates
|
6
6
|
|
7
|
-
|
7
|
+
def zomg?(*)
|
8
|
+
true
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
schema = Dry::Validation.Schema(predicates: predicates, build: false)
|
11
13
|
|
12
|
-
expect(schema.predicates
|
14
|
+
expect(schema.predicates[:key?]).to be_a(Method)
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -162,4 +162,12 @@ RSpec.describe Dry::Validation::Schema, 'defining key-based schema' do
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
end
|
165
|
+
|
166
|
+
context 'nested keys' do
|
167
|
+
it 'raises error when defining nested keys without `schema` block`' do
|
168
|
+
expect {
|
169
|
+
Dry::Validation.Schema { required(:foo).value { required(:bar).value(:str?) } }
|
170
|
+
}.to raise_error(ArgumentError, /required/)
|
171
|
+
end
|
172
|
+
end
|
165
173
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
shared_context 'predicate helper' do
|
1
|
+
RSpec.shared_context 'predicate helper' do
|
2
2
|
def p(name, *args)
|
3
|
-
predicates[name]
|
3
|
+
Dry::Logic::Rule::Predicate.new(predicates[name], args: args).to_ast
|
4
4
|
end
|
5
5
|
|
6
6
|
let!(:predicates) do
|
7
7
|
Module.new {
|
8
8
|
include Dry::Logic::Predicates
|
9
9
|
|
10
|
-
|
10
|
+
def self.email?(value)
|
11
|
+
true
|
12
|
+
end
|
11
13
|
}
|
12
14
|
end
|
13
15
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,6 +10,7 @@ if RUBY_ENGINE == "rbx"
|
|
10
10
|
end
|
11
11
|
|
12
12
|
require 'dry-validation'
|
13
|
+
require 'dry/core/constants'
|
13
14
|
require 'ostruct'
|
14
15
|
|
15
16
|
SPEC_ROOT = Pathname(__dir__)
|
@@ -18,6 +19,7 @@ Dir[SPEC_ROOT.join('shared/**/*.rb')].each(&method(:require))
|
|
18
19
|
Dir[SPEC_ROOT.join('support/**/*.rb')].each(&method(:require))
|
19
20
|
|
20
21
|
include Dry::Validation
|
22
|
+
include Dry::Core::Constants
|
21
23
|
|
22
24
|
module Types
|
23
25
|
include Dry::Types.module
|
@@ -38,4 +40,17 @@ RSpec.configure do |config|
|
|
38
40
|
end
|
39
41
|
|
40
42
|
config.include PredicatesIntegration
|
43
|
+
|
44
|
+
config.before do
|
45
|
+
module Test
|
46
|
+
def self.remove_constants
|
47
|
+
constants.each { |const| remove_const(const) }
|
48
|
+
self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
config.after do
|
54
|
+
Object.send(:remove_const, Test.remove_constants.name)
|
55
|
+
end
|
41
56
|
end
|