argspec 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +26 -6
- data/lib/argspec/argument.rb +37 -10
- data/lib/argspec/constants.rb +1 -1
- data/lib/argspec/dsl/matchers.rb +30 -0
- data/lib/argspec/dsl.rb +7 -29
- data/lib/argspec/matchers/base_matcher.rb +1 -1
- data/lib/argspec/matchers/be.rb +4 -12
- data/lib/argspec/matchers/be_compared_to.rb +89 -0
- data/lib/argspec/matchers/be_nil.rb +5 -1
- data/lib/argspec/matchers/be_one_of.rb +36 -0
- data/lib/argspec.rb +1 -0
- metadata +5 -6
- data/lib/argspec/matchers/be_greater_than.rb +0 -32
- data/lib/argspec/matchers/be_greater_than_or_equal_to.rb +0 -32
- data/lib/argspec/matchers/be_less_than.rb +0 -32
- data/lib/argspec/matchers/be_less_than_or_equal_to.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f6a9d2738f76290fa9b362e0b324eb6e60c3318
|
4
|
+
data.tar.gz: 5c70bae7e6ddd2d018ba54d42aaa81ba46f57414
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b49f0e5af1ee8057b7fe1bf820155b24b6242b3e7cf47f19c99f42d0916b63c14f33631b1deb9ad360b165467a26263a93ae473991aaa766926bc78ed54f4836
|
7
|
+
data.tar.gz: 7d260f1446eb41e61b7d54ca30d170c745f40e1a5d946fa8db8969e038370684d55a0553b1ba17c20d2c9e1603ac4e4f3d7300adf6c744139ac35840cca31ed6
|
data/README.md
CHANGED
@@ -61,13 +61,13 @@ class Person
|
|
61
61
|
attr_reader :name, :gender, :birthdate
|
62
62
|
|
63
63
|
def initialize(name, gender, birthdate)
|
64
|
-
argument(name)
|
65
|
-
|
66
|
-
|
64
|
+
argument(name) do
|
65
|
+
should be_a(String)
|
66
|
+
should_not be_empty
|
67
|
+
end
|
67
68
|
|
68
|
-
argument(
|
69
|
-
argument(
|
70
|
-
argument(birthdate).should_not(:be, nil)
|
69
|
+
argument(gender) { should be_a(Symbol) }
|
70
|
+
argument(birthdate) { should be_a(Date) }
|
71
71
|
|
72
72
|
@name = name
|
73
73
|
@gender = gender
|
@@ -78,6 +78,26 @@ end
|
|
78
78
|
|
79
79
|
That's better. It's now really clear what validations you're performing.
|
80
80
|
|
81
|
+
Method chaining is also supported:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
class Person
|
85
|
+
include ArgumentSpecification::DSL
|
86
|
+
|
87
|
+
attr_reader :name, :gender, :birthdate
|
88
|
+
|
89
|
+
def initialize(name, gender, birthdate)
|
90
|
+
argument(name) { should(be_a(Symbol)).and_not(be_empty) }
|
91
|
+
argument(gender) { should be_a(Symbol) }
|
92
|
+
argument(birthdate) { should be_a(Date) }
|
93
|
+
|
94
|
+
@name = name
|
95
|
+
@gender = gender
|
96
|
+
@birthdate = birthdate
|
97
|
+
end
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
81
101
|
## Development
|
82
102
|
|
83
103
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/argspec/argument.rb
CHANGED
@@ -1,19 +1,26 @@
|
|
1
1
|
module ArgumentSpecification
|
2
2
|
class Argument
|
3
|
+
include ArgumentSpecification::DSL::Matchers
|
4
|
+
|
3
5
|
attr_reader :actual
|
4
6
|
|
5
7
|
# Create a new argument
|
6
8
|
#
|
7
9
|
# Arguments:
|
8
10
|
# actual: (Object)
|
11
|
+
# block: (Block)
|
9
12
|
#
|
10
13
|
# Example:
|
11
14
|
# >> test = :test
|
12
|
-
# >> ArgumentSpecification::Argument.new(test)
|
15
|
+
# >> ArgumentSpecification::Argument.new(test) do
|
16
|
+
# >> should_not be_nil
|
17
|
+
# >> end
|
13
18
|
# => #<Argument:0x00000000000000 @actual=:test>
|
14
19
|
#
|
15
|
-
def initialize(actual)
|
20
|
+
def initialize(actual, &block)
|
16
21
|
@actual = actual
|
22
|
+
|
23
|
+
instance_eval(&block)
|
17
24
|
end
|
18
25
|
|
19
26
|
# Ensure the argument matches
|
@@ -22,18 +29,18 @@ module ArgumentSpecification
|
|
22
29
|
# matcher: (Matchers::BaseMatcher)
|
23
30
|
#
|
24
31
|
# Example:
|
25
|
-
# >>
|
26
|
-
# =>
|
32
|
+
# >> should be_a(Symbol)
|
33
|
+
# => #<Argument:0x00000000000000 @actual=:test>
|
27
34
|
#
|
28
35
|
# Raises:
|
29
36
|
# ArgumentError: When the argument does not match
|
30
37
|
#
|
31
38
|
def should(matcher)
|
32
|
-
return
|
39
|
+
return self unless matcher.is_a?(Matchers::BaseMatcher)
|
33
40
|
|
34
41
|
matcher.send(:actual=, @actual)
|
35
42
|
|
36
|
-
return
|
43
|
+
return self if matcher.matches?
|
37
44
|
|
38
45
|
raise ArgumentError, matcher.failure_message
|
39
46
|
end
|
@@ -44,20 +51,40 @@ module ArgumentSpecification
|
|
44
51
|
# matcher: (Matchers::BaseMatcher)
|
45
52
|
#
|
46
53
|
# Example:
|
47
|
-
# >>
|
48
|
-
# =>
|
54
|
+
# >> should_not be_a(Symbol)
|
55
|
+
# => #<Argument:0x00000000000000 @actual=:test>
|
49
56
|
#
|
50
57
|
# Raises:
|
51
58
|
# ArgumentError: When the argument matches
|
52
59
|
#
|
53
60
|
def should_not(matcher)
|
54
|
-
return
|
61
|
+
return self unless matcher.is_a?(Matchers::BaseMatcher)
|
55
62
|
|
56
63
|
matcher.send(:actual=, @actual)
|
57
64
|
|
58
|
-
return
|
65
|
+
return self unless matcher.matches?
|
59
66
|
|
60
67
|
raise ArgumentError, matcher.failure_message_when_negated
|
61
68
|
end
|
69
|
+
|
70
|
+
# Alias for should
|
71
|
+
#
|
72
|
+
# Example:
|
73
|
+
# >> and be_a(Symbol)
|
74
|
+
# => #<Argument:0x00000000000000 @actual=:test>
|
75
|
+
#
|
76
|
+
def and(*args)
|
77
|
+
should(*args)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Alias for should_not
|
81
|
+
#
|
82
|
+
# Example:
|
83
|
+
# >> and_not be_a(Symbol)
|
84
|
+
# => #<Argument:0x00000000000000 @actual=:test>
|
85
|
+
#
|
86
|
+
def and_not(*args)
|
87
|
+
should_not(*args)
|
88
|
+
end
|
62
89
|
end
|
63
90
|
end
|
data/lib/argspec/constants.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
module ArgumentSpecification
|
2
|
+
module DSL
|
3
|
+
module Matchers
|
4
|
+
class << self
|
5
|
+
# Register a matcher
|
6
|
+
#
|
7
|
+
# Arguments:
|
8
|
+
# klass: (ArgumentSpecification::Matchers::BaseMatcher)
|
9
|
+
# name: (Symbol)
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
# >> Matchers.register(TestMatcher, :test_matcher)
|
13
|
+
# => true
|
14
|
+
#
|
15
|
+
def register(klass, name)
|
16
|
+
return unless klass.ancestors.include?(ArgumentSpecification::Matchers::BaseMatcher)
|
17
|
+
return unless name.is_a?(Symbol)
|
18
|
+
|
19
|
+
module_eval <<-EOS
|
20
|
+
def #{name}(*args, &block)
|
21
|
+
instance = #{klass}.new(*args, &block)
|
22
|
+
instance.send(:setup, '#{name}'.to_sym, args)
|
23
|
+
instance
|
24
|
+
end
|
25
|
+
EOS
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/argspec/dsl.rb
CHANGED
@@ -1,42 +1,20 @@
|
|
1
1
|
module ArgumentSpecification
|
2
2
|
module DSL
|
3
|
-
class << self
|
4
|
-
# Register a matcher
|
5
|
-
#
|
6
|
-
# Arguments:
|
7
|
-
# klass: (Matchers::BaseMatcher)
|
8
|
-
# name: (Symbol)
|
9
|
-
#
|
10
|
-
# Example:
|
11
|
-
# >> register_matcher(TestMatcher, :test_matcher)
|
12
|
-
# => true
|
13
|
-
#
|
14
|
-
def register_matcher(klass, name)
|
15
|
-
return unless klass.ancestors.include?(Matchers::BaseMatcher)
|
16
|
-
return unless name.is_a?(Symbol)
|
17
|
-
|
18
|
-
module_eval <<-EOS
|
19
|
-
def #{name}(*args, &block)
|
20
|
-
instance = #{klass}.new(*args, &block)
|
21
|
-
instance.send(:setup, '#{name}'.to_sym, args)
|
22
|
-
instance
|
23
|
-
end
|
24
|
-
EOS
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
3
|
# Get an argument object
|
29
4
|
#
|
30
5
|
# Arguments:
|
31
6
|
# object: (Object)
|
7
|
+
# block: (Block)
|
32
8
|
#
|
33
9
|
# Example:
|
34
10
|
# >> test = :test
|
35
|
-
# >> argument(test)
|
36
|
-
# =>
|
11
|
+
# >> argument(test) { should_not be_nil }
|
12
|
+
# => nil
|
37
13
|
#
|
38
|
-
def argument(object)
|
39
|
-
ArgumentSpecification::Argument.new(object)
|
14
|
+
def argument(object, &block)
|
15
|
+
ArgumentSpecification::Argument.new(object, &block)
|
16
|
+
|
17
|
+
nil
|
40
18
|
end
|
41
19
|
end
|
42
20
|
end
|
data/lib/argspec/matchers/be.rb
CHANGED
@@ -3,19 +3,11 @@ module ArgumentSpecification
|
|
3
3
|
class Be < BaseMatcher
|
4
4
|
matcher_name :be
|
5
5
|
|
6
|
-
|
7
|
-
:== => :equal,
|
8
|
-
:=== => :case_equal,
|
9
|
-
:=~ => :match,
|
10
|
-
:< => :be_less_than,
|
11
|
-
:> => :be_greater_than,
|
12
|
-
:<= => :be_less_than_or_equal_to,
|
13
|
-
:>= => :be_greater_than_or_equal_to
|
14
|
-
}
|
15
|
-
|
16
|
-
OPERATORS.keys.each do |operator|
|
6
|
+
[:==, :===, :=~, :<, :>, :<=, :>=].each do |operator|
|
17
7
|
define_method(operator) do |expected|
|
18
|
-
|
8
|
+
instance = BeComparedTo.new(operator, expected)
|
9
|
+
instance.send(:setup, operator, [operator, expected])
|
10
|
+
instance
|
19
11
|
end
|
20
12
|
end
|
21
13
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ArgumentSpecification
|
2
|
+
module Matchers
|
3
|
+
class BeComparedTo < BaseMatcher
|
4
|
+
attr_reader :operator, :expected
|
5
|
+
|
6
|
+
# Create a new matcher instance
|
7
|
+
#
|
8
|
+
# Arguments:
|
9
|
+
# operator: (Symbol)
|
10
|
+
# expected: (Object)
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# >> ArgumentSpecification::Matchers::BeComparedTo.new(:==, 10)
|
14
|
+
# => #<ArgumentSpecification::Matchers::BeComparedTo:0x00000000000000 @operator=:==, @expected=10>
|
15
|
+
#
|
16
|
+
def initialize(operator, expected)
|
17
|
+
@operator = operator
|
18
|
+
@expected = expected
|
19
|
+
end
|
20
|
+
|
21
|
+
# The failure message when using 'should'
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# >> matcher.failure_message
|
25
|
+
# => "':foo' should be equal to ':test'"
|
26
|
+
#
|
27
|
+
def failure_message
|
28
|
+
actual = prettify_args(@actual)
|
29
|
+
|
30
|
+
"'#{actual}' should #{pretty_matcher} '#{@expected}'"
|
31
|
+
end
|
32
|
+
|
33
|
+
# The failure message when using 'should not'
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
# >> matcher.failure_message_when_negated
|
37
|
+
# => "':test' should not be equal to ':test'"
|
38
|
+
#
|
39
|
+
def failure_message_when_negated
|
40
|
+
actual = prettify_args(@actual)
|
41
|
+
|
42
|
+
"'#{actual}' should not #{pretty_matcher} '#{@expected}'"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check if the actual object matches
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# >> matcher.matches?
|
49
|
+
# => true
|
50
|
+
#
|
51
|
+
def matches?
|
52
|
+
begin
|
53
|
+
@actual.send(@operator, @expected)
|
54
|
+
rescue ArgumentError
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
# Get the pretty matcher name
|
61
|
+
#
|
62
|
+
# Example:
|
63
|
+
# >> matcher = BeComparedTo.new(:==, 1)
|
64
|
+
# >> matcher.pretty_matcher
|
65
|
+
# => "equal"
|
66
|
+
#
|
67
|
+
def pretty_matcher
|
68
|
+
case @operator
|
69
|
+
when :==
|
70
|
+
"equal"
|
71
|
+
when :===
|
72
|
+
"case equal"
|
73
|
+
when :=~
|
74
|
+
"match"
|
75
|
+
when :<
|
76
|
+
"be less than"
|
77
|
+
when :>
|
78
|
+
"be greater than"
|
79
|
+
when :<=
|
80
|
+
"be less than or equal to"
|
81
|
+
when :>=
|
82
|
+
"be greater than or equal to"
|
83
|
+
else
|
84
|
+
"pass comparison #{@operator} to"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ArgumentSpecification
|
2
|
+
module Matchers
|
3
|
+
class BeOneOf < BaseMatcher
|
4
|
+
matcher_name :be_one_of
|
5
|
+
|
6
|
+
attr_reader :values
|
7
|
+
|
8
|
+
# Create a new matcher instance
|
9
|
+
#
|
10
|
+
# Arguments:
|
11
|
+
# values: (Splat|Range)
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# >> ArgumentSpecification::Matchers::BeOneOf.new(1, 2)
|
15
|
+
# => #<ArgumentSpecification::Matchers::BeOneOf:0x00000000000000 @values=[1, 2]>
|
16
|
+
#
|
17
|
+
def initialize(*values)
|
18
|
+
if values && values.first.is_a?(Range)
|
19
|
+
@values = values.first.to_a
|
20
|
+
else
|
21
|
+
@values = values
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if the actual object matches
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# >> matcher.matches?
|
29
|
+
# => true
|
30
|
+
#
|
31
|
+
def matches?
|
32
|
+
@values.include?(@actual)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/argspec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nialto Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,18 +72,17 @@ files:
|
|
72
72
|
- lib/argspec/argument.rb
|
73
73
|
- lib/argspec/constants.rb
|
74
74
|
- lib/argspec/dsl.rb
|
75
|
+
- lib/argspec/dsl/matchers.rb
|
75
76
|
- lib/argspec/matchers.rb
|
76
77
|
- lib/argspec/matchers/all.rb
|
77
78
|
- lib/argspec/matchers/base_matcher.rb
|
78
79
|
- lib/argspec/matchers/be.rb
|
79
80
|
- lib/argspec/matchers/be_a.rb
|
81
|
+
- lib/argspec/matchers/be_compared_to.rb
|
80
82
|
- lib/argspec/matchers/be_empty.rb
|
81
83
|
- lib/argspec/matchers/be_falsey.rb
|
82
|
-
- lib/argspec/matchers/be_greater_than.rb
|
83
|
-
- lib/argspec/matchers/be_greater_than_or_equal_to.rb
|
84
|
-
- lib/argspec/matchers/be_less_than.rb
|
85
|
-
- lib/argspec/matchers/be_less_than_or_equal_to.rb
|
86
84
|
- lib/argspec/matchers/be_nil.rb
|
85
|
+
- lib/argspec/matchers/be_one_of.rb
|
87
86
|
- lib/argspec/matchers/be_truthy.rb
|
88
87
|
- lib/argspec/matchers/be_within_range.rb
|
89
88
|
- lib/argspec/matchers/case_equal.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module ArgumentSpecification
|
2
|
-
module Matchers
|
3
|
-
class BeGreaterThan < BaseMatcher
|
4
|
-
matcher_name :be_greater_than
|
5
|
-
|
6
|
-
attr_reader :expected
|
7
|
-
|
8
|
-
# Create a new matcher instance
|
9
|
-
#
|
10
|
-
# Arguments:
|
11
|
-
# expected: (Object)
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# >> ArgumentSpecification::Matchers::BeGreaterThan.new(10)
|
15
|
-
# => #<ArgumentSpecification::Matchers::BeGreaterThan:0x00000000000000 @expected=10>
|
16
|
-
#
|
17
|
-
def initialize(expected)
|
18
|
-
@expected = expected
|
19
|
-
end
|
20
|
-
|
21
|
-
# Check if the actual object matches
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
# >> matcher.matches?
|
25
|
-
# => true
|
26
|
-
#
|
27
|
-
def matches?
|
28
|
-
@actual > @expected
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module ArgumentSpecification
|
2
|
-
module Matchers
|
3
|
-
class BeGreaterThanOrEqualTo < BaseMatcher
|
4
|
-
matcher_name :be_greater_than_or_equal_to
|
5
|
-
|
6
|
-
attr_reader :expected
|
7
|
-
|
8
|
-
# Create a new matcher instance
|
9
|
-
#
|
10
|
-
# Arguments:
|
11
|
-
# expected: (Object)
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# >> ArgumentSpecification::Matchers::BeGreaterThanOrEqualTo.new(10)
|
15
|
-
# => #<ArgumentSpecification::Matchers::BeGreaterThanOrEqualTo:0x00000000000000 @expected=10>
|
16
|
-
#
|
17
|
-
def initialize(expected)
|
18
|
-
@expected = expected
|
19
|
-
end
|
20
|
-
|
21
|
-
# Check if the actual object matches
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
# >> matcher.matches?
|
25
|
-
# => true
|
26
|
-
#
|
27
|
-
def matches?
|
28
|
-
@actual >= @expected
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module ArgumentSpecification
|
2
|
-
module Matchers
|
3
|
-
class BeLessThan < BaseMatcher
|
4
|
-
matcher_name :be_less_than
|
5
|
-
|
6
|
-
attr_reader :expected
|
7
|
-
|
8
|
-
# Create a new matcher instance
|
9
|
-
#
|
10
|
-
# Arguments:
|
11
|
-
# expected: (Object)
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# >> ArgumentSpecification::Matchers::BeLessThan.new(10)
|
15
|
-
# => #<ArgumentSpecification::Matchers::BeLessThan:0x00000000000000 @expected=10>
|
16
|
-
#
|
17
|
-
def initialize(expected)
|
18
|
-
@expected = expected
|
19
|
-
end
|
20
|
-
|
21
|
-
# Check if the actual object matches
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
# >> matcher.matches?
|
25
|
-
# => true
|
26
|
-
#
|
27
|
-
def matches?
|
28
|
-
@actual < @expected
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module ArgumentSpecification
|
2
|
-
module Matchers
|
3
|
-
class BeLessThanOrEqualTo < BaseMatcher
|
4
|
-
matcher_name :be_less_than_or_equal_to
|
5
|
-
|
6
|
-
attr_reader :expected
|
7
|
-
|
8
|
-
# Create a new matcher instance
|
9
|
-
#
|
10
|
-
# Arguments:
|
11
|
-
# expected: (Object)
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# >> ArgumentSpecification::Matchers::BeLessThanOrEqualTo.new(10)
|
15
|
-
# => #<ArgumentSpecification::Matchers::BeLessThanOrEqualTo:0x00000000000000 @expected=10>
|
16
|
-
#
|
17
|
-
def initialize(expected)
|
18
|
-
@expected = expected
|
19
|
-
end
|
20
|
-
|
21
|
-
# Check if the actual object matches
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
# >> matcher.matches?
|
25
|
-
# => true
|
26
|
-
#
|
27
|
-
def matches?
|
28
|
-
@actual <= @expected
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|