striuct 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.gitignore +35 -34
  2. data/.travis.yml +6 -6
  3. data/Gemfile +12 -12
  4. data/History.rdoc +279 -273
  5. data/LICENSE +21 -21
  6. data/Manifest.txt +91 -90
  7. data/README.ja.old.rdoc +297 -297
  8. data/README.md +128 -128
  9. data/Rakefile +11 -11
  10. data/benchmark/basics.rb +56 -56
  11. data/example/README.rb +44 -44
  12. data/example/example.old.rdoc +187 -187
  13. data/example/example1.rb +233 -233
  14. data/example/example2.rb +22 -22
  15. data/example/see_trace.rb +32 -32
  16. data/lib/striuct/classmethods/README.md +5 -5
  17. data/lib/striuct/classmethods/adjustment.rb +32 -32
  18. data/lib/striuct/classmethods/constructor.rb +63 -63
  19. data/lib/striuct/classmethods/default.rb +27 -27
  20. data/lib/striuct/classmethods/enum.rb +48 -48
  21. data/lib/striuct/classmethods/inner.rb +91 -91
  22. data/lib/striuct/classmethods/length.rb +14 -14
  23. data/lib/striuct/classmethods/macro.rb +144 -144
  24. data/lib/striuct/classmethods/named.rb +113 -113
  25. data/lib/striuct/classmethods/object.rb +54 -54
  26. data/lib/striuct/classmethods/prevent_conflicts.rb +89 -89
  27. data/lib/striuct/classmethods/requiremnets.rb +11 -11
  28. data/lib/striuct/classmethods/to_struct.rb +23 -25
  29. data/lib/striuct/classmethods/validation.rb +55 -55
  30. data/lib/striuct/classmethods.rb +1 -1
  31. data/lib/striuct/instancemethods/README.md +5 -5
  32. data/lib/striuct/instancemethods/assign.rb +30 -30
  33. data/lib/striuct/instancemethods/cast.rb +34 -34
  34. data/lib/striuct/instancemethods/compare.rb +30 -30
  35. data/lib/striuct/instancemethods/default.rb +13 -13
  36. data/lib/striuct/instancemethods/delegate_class_methods.rb +28 -28
  37. data/lib/striuct/instancemethods/enum.rb +103 -103
  38. data/lib/striuct/instancemethods/hashy.rb +121 -121
  39. data/lib/striuct/instancemethods/inner.rb +60 -60
  40. data/lib/striuct/instancemethods/keyvalidatable.rb +14 -14
  41. data/lib/striuct/instancemethods/lock.rb +61 -61
  42. data/lib/striuct/instancemethods/object.rb +52 -52
  43. data/lib/striuct/instancemethods/requirements.rb +14 -14
  44. data/lib/striuct/instancemethods/safety.rb +11 -11
  45. data/lib/striuct/instancemethods/subscript.rb +55 -55
  46. data/lib/striuct/instancemethods/validation.rb +29 -25
  47. data/lib/striuct/instancemethods/values.rb +57 -57
  48. data/lib/striuct/instancemethods.rb +1 -1
  49. data/lib/striuct/requirements.rb +5 -5
  50. data/lib/striuct/singleton_class.rb +66 -66
  51. data/lib/striuct/specificcontainer.rb +19 -19
  52. data/lib/striuct/structs.rb +7 -7
  53. data/lib/striuct/version.rb +5 -5
  54. data/lib/striuct.rb +13 -13
  55. data/striuct.gemspec +24 -24
  56. data/test/helper.rb +5 -5
  57. data/test/test_striuct-singleton_class-define.rb +19 -19
  58. data/test/test_striuct-subclass-class-cloning.rb +20 -20
  59. data/test/test_striuct-subclass-class-close.rb +36 -36
  60. data/test/test_striuct-subclass-class-constructor.rb +82 -82
  61. data/test/test_striuct-subclass-class-freeze.rb +36 -36
  62. data/test/test_striuct-subclass-class-inheritable.rb +57 -57
  63. data/test/test_striuct-subclass-class-macro.rb +13 -13
  64. data/test/test_striuct-subclass-class-safety_naming.rb +72 -72
  65. data/test/test_striuct-subclass-class-validation.rb +26 -26
  66. data/test/test_striuct-subclass-feature-alias_member.rb +53 -53
  67. data/test/test_striuct-subclass-feature-to_struct.rb +61 -25
  68. data/test/test_striuct-subclass-feature-validation_util.rb +57 -0
  69. data/test/test_striuct-subclass-instance-accessor.rb +137 -137
  70. data/test/test_striuct-subclass-instance-adjuster.rb +94 -94
  71. data/test/test_striuct-subclass-instance-assign.rb +30 -30
  72. data/test/test_striuct-subclass-instance-basic.rb +32 -32
  73. data/test/test_striuct-subclass-instance-cloning.rb +22 -22
  74. data/test/test_striuct-subclass-instance-compare.rb +51 -51
  75. data/test/test_striuct-subclass-instance-default_value.rb +128 -128
  76. data/test/test_striuct-subclass-instance-enum.rb +92 -92
  77. data/test/test_striuct-subclass-instance-freeze.rb +19 -19
  78. data/test/test_striuct-subclass-instance-hashlike.rb +153 -153
  79. data/test/test_striuct-subclass-instance-keyvalidatable.rb +24 -24
  80. data/test/test_striuct-subclass-instance-lock.rb +39 -39
  81. data/test/test_striuct-subclass-instance-to_s_family.rb +25 -25
  82. data/test/test_striuct-subclass-instance-validation_functional_condition.rb +50 -50
  83. data/test/test_striuct-subclass-instance-validation_inference.rb +50 -50
  84. data/test/test_striuct-subclass-instance-validation_specific_conditions.rb +247 -247
  85. data/test/test_striuct-subclass-instance-validation_with_getter.rb +33 -33
  86. data/test/test_striuct-subclass-instance_names.rb +18 -18
  87. data/test/test_striuct-version.rb +10 -10
  88. metadata +4 -2
@@ -1,52 +1,52 @@
1
- require_relative 'helper'
2
-
3
-
4
- class Test_Striuct_Subclass_Instance_Compare < Test::Unit::TestCase
5
-
6
- class User < Striuct.new
7
- member :id, Integer
8
- member :last_name, /\A\w+\z/
9
- member :family_name, /\A\w+\z/
10
- member :address, /\A((\w+) ?)+\z/
11
- member :age, ->age{(20..140).include? age}
12
- end
13
-
14
- def setup
15
- @user = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
16
- @user2 = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
17
- end
18
-
19
- def test_hash
20
- assert_kind_of Integer, @user.hash
21
- assert_equal @user.hash, @user2.hash
22
- end
23
-
24
- def test_eql?
25
- assert_equal true, @user.eql?(@user2)
26
- assert_equal true, @user2.eql?(@user)
27
- assert_equal false, @user.eql?(User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 31)
28
- end
29
-
30
- def test_equal
31
- user1 = User.new 11218, 'taro'
32
- user2 = User.new 11218, 'taro'
33
- assert_equal true, (user1 == user2)
34
- user2.last_name = 'ichiro'
35
- assert_equal false, (user1 == user2)
36
- end
37
-
38
- Sth = Striuct.new :foo, :bar, :hoge
39
-
40
- def test_hashkeyable
41
- sth1 = Sth[hoge: 7, foo: 8]
42
- sth2 = Sth[hoge: 7, foo: 8]
43
- assert_equal true, sth1.eql?(sth2)
44
- assert_equal true, sth2.eql?(sth1)
45
- assert_equal sth1.hash, sth2.hash
46
- assert_equal true, {sth1 => 1}.has_key?(sth2)
47
- assert_equal true, {sth2 => 1}.has_key?(sth1)
48
- assert_equal 1, {sth1 => 1}[sth2]
49
- assert_equal 1, {sth2 => 1}[sth1]
50
- end
51
-
1
+ require_relative 'helper'
2
+
3
+
4
+ class Test_Striuct_Subclass_Instance_Compare < Test::Unit::TestCase
5
+
6
+ class User < Striuct.new
7
+ member :id, Integer
8
+ member :last_name, /\A\w+\z/
9
+ member :family_name, /\A\w+\z/
10
+ member :address, /\A((\w+) ?)+\z/
11
+ member :age, ->age{(20..140).include? age}
12
+ end
13
+
14
+ def setup
15
+ @user = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
16
+ @user2 = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
17
+ end
18
+
19
+ def test_hash
20
+ assert_kind_of Integer, @user.hash
21
+ assert_equal @user.hash, @user2.hash
22
+ end
23
+
24
+ def test_eql?
25
+ assert_equal true, @user.eql?(@user2)
26
+ assert_equal true, @user2.eql?(@user)
27
+ assert_equal false, @user.eql?(User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 31)
28
+ end
29
+
30
+ def test_equal
31
+ user1 = User.new 11218, 'taro'
32
+ user2 = User.new 11218, 'taro'
33
+ assert_equal true, (user1 == user2)
34
+ user2.last_name = 'ichiro'
35
+ assert_equal false, (user1 == user2)
36
+ end
37
+
38
+ Sth = Striuct.new :foo, :bar, :hoge
39
+
40
+ def test_hashkeyable
41
+ sth1 = Sth[hoge: 7, foo: 8]
42
+ sth2 = Sth[hoge: 7, foo: 8]
43
+ assert_equal true, sth1.eql?(sth2)
44
+ assert_equal true, sth2.eql?(sth1)
45
+ assert_equal sth1.hash, sth2.hash
46
+ assert_equal true, {sth1 => 1}.has_key?(sth2)
47
+ assert_equal true, {sth2 => 1}.has_key?(sth1)
48
+ assert_equal 1, {sth1 => 1}[sth2]
49
+ assert_equal 1, {sth2 => 1}[sth1]
50
+ end
51
+
52
52
  end
@@ -1,129 +1,129 @@
1
- require_relative 'helper'
2
-
3
- class Test_Striuct_Subclass_Instance_Default_Value < Test::Unit::TestCase
4
-
5
- Sth = Striuct.new do
6
- member :lank, OR(Bignum, Fixnum)
7
- default :lank, 1
8
- end
9
-
10
- def test_default
11
- sth = Sth.new 2
12
- assert_equal 2, sth.lank
13
- sth = Sth.new
14
- assert_equal 1, sth.lank
15
- assert_equal true, sth.default?(:lank)
16
- sth.lank = 2
17
- assert_equal false, sth.default?(:lank)
18
- end
19
-
20
- def test_define_default
21
- assert_raises NameError do
22
- Sth.class_eval do
23
- default :anything, 10
24
- end
25
- end
26
-
27
- klass = Striuct.define do
28
- member :lank2, Integer
29
- default :lank2, '10'
30
- end
31
-
32
- assert_raises Validation::InvalidWritingError do
33
- klass.new
34
- end
35
-
36
- scope = self
37
- seef = nil
38
- klass = Striuct.define do
39
- member :lank, Integer
40
-
41
- scope.assert_raises ArgumentError do
42
- default :lank, &->own, name, exess{rand}
43
- end
44
-
45
- scope.assert_raises ArgumentError do
46
- default :lank, '10', &->own, name{rand}
47
- end
48
-
49
- scope.assert_raises ArgumentError do
50
- default :lank, '10', &->own{rand}
51
- end
52
-
53
- scope.assert_raises ArgumentError do
54
- default :lank, '10', &->{rand}
55
- end
56
-
57
- default :lank, &->own, name{(seef = own); rand}
58
- end
59
-
60
- assert_raises Validation::InvalidWritingError do
61
- klass.new
62
- end
63
-
64
- klass = Striuct.define do
65
- member :lank, Integer
66
- default :lank, &->own, name{(seef = own); 10 - name.length}
67
- end
68
-
69
- assert_equal 6, klass.new.lank
70
- assert_equal seef, klass.new
71
- end
72
-
73
- end
74
-
75
- class Test_Striuct_Subclass_Instance_DefaultValue_Under_MemberMacro < Test::Unit::TestCase
76
-
77
- Sth = Striuct.new do
78
- member :lank, OR(Bignum, Fixnum), default: 1
79
- end
80
-
81
- def test_default
82
- sth = Sth.new 2
83
- assert_equal 2, sth.lank
84
- sth = Sth.new
85
- assert_equal 1, sth.lank
86
- assert_equal true, sth.default?(:lank)
87
- sth.lank = 2
88
- assert_equal false, sth.default?(:lank)
89
- end
90
-
91
- def test_define_default
92
- assert_raises NameError do
93
- Sth.class_eval do
94
- default :anything, 10
95
- end
96
- end
97
-
98
- klass = Striuct.define do
99
- member :lank2, Integer, default: '10'
100
- end
101
-
102
- assert_raises Validation::InvalidWritingError do
103
- klass.new
104
- end
105
-
106
- scope = self
107
- seef = nil
108
- klass = Striuct.define do
109
-
110
- scope.assert_raises ArgumentError do
111
- member :lank, Integer, default: '10', default_proc: ->own,name{rand}
112
- end
113
-
114
- member :lank, Integer, default_proc: ->own,name{(seef = own); rand}
115
- end
116
-
117
- assert_raises Validation::InvalidWritingError do
118
- klass.new
119
- end
120
-
121
- klass = Striuct.define do
122
- member :lank, Integer, default_proc: ->own,name{(seef = own); 10 - name.length}
123
- end
124
-
125
- assert_equal 6, klass.new.lank
126
- assert_equal seef, klass.new
127
- end
128
-
1
+ require_relative 'helper'
2
+
3
+ class Test_Striuct_Subclass_Instance_Default_Value < Test::Unit::TestCase
4
+
5
+ Sth = Striuct.new do
6
+ member :lank, OR(Bignum, Fixnum)
7
+ default :lank, 1
8
+ end
9
+
10
+ def test_default
11
+ sth = Sth.new 2
12
+ assert_equal 2, sth.lank
13
+ sth = Sth.new
14
+ assert_equal 1, sth.lank
15
+ assert_equal true, sth.default?(:lank)
16
+ sth.lank = 2
17
+ assert_equal false, sth.default?(:lank)
18
+ end
19
+
20
+ def test_define_default
21
+ assert_raises NameError do
22
+ Sth.class_eval do
23
+ default :anything, 10
24
+ end
25
+ end
26
+
27
+ klass = Striuct.define do
28
+ member :lank2, Integer
29
+ default :lank2, '10'
30
+ end
31
+
32
+ assert_raises Validation::InvalidWritingError do
33
+ klass.new
34
+ end
35
+
36
+ scope = self
37
+ seef = nil
38
+ klass = Striuct.define do
39
+ member :lank, Integer
40
+
41
+ scope.assert_raises ArgumentError do
42
+ default :lank, &->own, name, exess{rand}
43
+ end
44
+
45
+ scope.assert_raises ArgumentError do
46
+ default :lank, '10', &->own, name{rand}
47
+ end
48
+
49
+ scope.assert_raises ArgumentError do
50
+ default :lank, '10', &->own{rand}
51
+ end
52
+
53
+ scope.assert_raises ArgumentError do
54
+ default :lank, '10', &->{rand}
55
+ end
56
+
57
+ default :lank, &->own, name{(seef = own); rand}
58
+ end
59
+
60
+ assert_raises Validation::InvalidWritingError do
61
+ klass.new
62
+ end
63
+
64
+ klass = Striuct.define do
65
+ member :lank, Integer
66
+ default :lank, &->own, name{(seef = own); 10 - name.length}
67
+ end
68
+
69
+ assert_equal 6, klass.new.lank
70
+ assert_equal seef, klass.new
71
+ end
72
+
73
+ end
74
+
75
+ class Test_Striuct_Subclass_Instance_DefaultValue_Under_MemberMacro < Test::Unit::TestCase
76
+
77
+ Sth = Striuct.new do
78
+ member :lank, OR(Bignum, Fixnum), default: 1
79
+ end
80
+
81
+ def test_default
82
+ sth = Sth.new 2
83
+ assert_equal 2, sth.lank
84
+ sth = Sth.new
85
+ assert_equal 1, sth.lank
86
+ assert_equal true, sth.default?(:lank)
87
+ sth.lank = 2
88
+ assert_equal false, sth.default?(:lank)
89
+ end
90
+
91
+ def test_define_default
92
+ assert_raises NameError do
93
+ Sth.class_eval do
94
+ default :anything, 10
95
+ end
96
+ end
97
+
98
+ klass = Striuct.define do
99
+ member :lank2, Integer, default: '10'
100
+ end
101
+
102
+ assert_raises Validation::InvalidWritingError do
103
+ klass.new
104
+ end
105
+
106
+ scope = self
107
+ seef = nil
108
+ klass = Striuct.define do
109
+
110
+ scope.assert_raises ArgumentError do
111
+ member :lank, Integer, default: '10', default_proc: ->own,name{rand}
112
+ end
113
+
114
+ member :lank, Integer, default_proc: ->own,name{(seef = own); rand}
115
+ end
116
+
117
+ assert_raises Validation::InvalidWritingError do
118
+ klass.new
119
+ end
120
+
121
+ klass = Striuct.define do
122
+ member :lank, Integer, default_proc: ->own,name{(seef = own); 10 - name.length}
123
+ end
124
+
125
+ assert_equal 6, klass.new.lank
126
+ assert_equal seef, klass.new
127
+ end
128
+
129
129
  end
@@ -1,93 +1,93 @@
1
- require_relative 'helper'
2
-
3
-
4
- class Test_Striuct_Subclass_Instance_Enum < Test::Unit::TestCase
5
-
6
- class User < Striuct.new
7
- member :id, Integer
8
- member :last_name, /\A\w+\z/
9
- member :family_name, /\A\w+\z/
10
- member :address, /\A((\w+) ?)+\z/
11
- member :age, ->age{(20..140).include? age}
12
- end
13
-
14
- def setup
15
- @user = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
16
- @user2 = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
17
- end
18
-
19
- def test_each
20
- assert_same @user, @user.each{}
21
- assert_kind_of Enumerator, enum = @user.each
22
- assert_equal enum.next, 9999
23
- assert_equal enum.next, 'taro'
24
- end
25
-
26
- def test_each_member
27
- assert_same @user, @user.each_member{}
28
- assert_kind_of Enumerator, enum = @user.each_member
29
- assert_equal :id, enum.next
30
- assert_equal :last_name, enum.next
31
- assert_equal :family_name, enum.next
32
- assert_equal :address, enum.next
33
- assert_equal :age, enum.next
34
- assert_raises StopIteration do
35
- enum.next
36
- end
37
- end
38
-
39
- def test_each_index
40
- assert_same @user, @user.each_index{}
41
- assert_kind_of Enumerator, enum = @user.each_index
42
- assert_equal 0, enum.next
43
- assert_equal 1, enum.next
44
- assert_equal 2, enum.next
45
- assert_equal 3, enum.next
46
- assert_equal 4, enum.next
47
- assert_raises StopIteration do
48
- enum.next
49
- end
50
- end
51
-
52
- def test_each_with_index
53
- assert_same @user, @user.each_with_index{}
54
- assert_kind_of Enumerator, @user.each_with_index
55
-
56
- r = []
57
- @user.each_with_index do |value, index|
58
- r << [value, index]
59
- end
60
-
61
- assert_equal [@user.each_value.to_a, @user.each_index.to_a].transpose, r
62
- end
63
-
64
- def test_each_member_with_index
65
- assert_same @user, @user.each_member_with_index{}
66
- assert_kind_of Enumerator, @user.each_member_with_index
67
-
68
- r = []
69
- @user.each_member_with_index do |name, index|
70
- r << [name, index]
71
- end
72
-
73
- assert_equal [@user.each_key.to_a, @user.each_index.to_a].transpose, r
74
- end
75
-
76
- Sth = Striuct.define do
77
- member :name
78
- member :age
79
- end
80
-
81
- def test_each_pair_with_index
82
- sth = Sth.new 'a', 10
83
- assert_same sth, sth.each_pair_with_index{}
84
-
85
- enum = sth.each_pair_with_index
86
- assert_equal [:name, 'a', 0], enum.next
87
- assert_equal [:age, 10, 1], enum.next
88
- assert_raises StopIteration do
89
- enum.next
90
- end
91
- end
92
-
1
+ require_relative 'helper'
2
+
3
+
4
+ class Test_Striuct_Subclass_Instance_Enum < Test::Unit::TestCase
5
+
6
+ class User < Striuct.new
7
+ member :id, Integer
8
+ member :last_name, /\A\w+\z/
9
+ member :family_name, /\A\w+\z/
10
+ member :address, /\A((\w+) ?)+\z/
11
+ member :age, ->age{(20..140).include? age}
12
+ end
13
+
14
+ def setup
15
+ @user = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
16
+ @user2 = User.new 9999, 'taro', 'yamada', 'Tokyo Japan', 30
17
+ end
18
+
19
+ def test_each
20
+ assert_same @user, @user.each{}
21
+ assert_kind_of Enumerator, enum = @user.each
22
+ assert_equal enum.next, 9999
23
+ assert_equal enum.next, 'taro'
24
+ end
25
+
26
+ def test_each_member
27
+ assert_same @user, @user.each_member{}
28
+ assert_kind_of Enumerator, enum = @user.each_member
29
+ assert_equal :id, enum.next
30
+ assert_equal :last_name, enum.next
31
+ assert_equal :family_name, enum.next
32
+ assert_equal :address, enum.next
33
+ assert_equal :age, enum.next
34
+ assert_raises StopIteration do
35
+ enum.next
36
+ end
37
+ end
38
+
39
+ def test_each_index
40
+ assert_same @user, @user.each_index{}
41
+ assert_kind_of Enumerator, enum = @user.each_index
42
+ assert_equal 0, enum.next
43
+ assert_equal 1, enum.next
44
+ assert_equal 2, enum.next
45
+ assert_equal 3, enum.next
46
+ assert_equal 4, enum.next
47
+ assert_raises StopIteration do
48
+ enum.next
49
+ end
50
+ end
51
+
52
+ def test_each_with_index
53
+ assert_same @user, @user.each_with_index{}
54
+ assert_kind_of Enumerator, @user.each_with_index
55
+
56
+ r = []
57
+ @user.each_with_index do |value, index|
58
+ r << [value, index]
59
+ end
60
+
61
+ assert_equal [@user.each_value.to_a, @user.each_index.to_a].transpose, r
62
+ end
63
+
64
+ def test_each_member_with_index
65
+ assert_same @user, @user.each_member_with_index{}
66
+ assert_kind_of Enumerator, @user.each_member_with_index
67
+
68
+ r = []
69
+ @user.each_member_with_index do |name, index|
70
+ r << [name, index]
71
+ end
72
+
73
+ assert_equal [@user.each_key.to_a, @user.each_index.to_a].transpose, r
74
+ end
75
+
76
+ Sth = Striuct.define do
77
+ member :name
78
+ member :age
79
+ end
80
+
81
+ def test_each_pair_with_index
82
+ sth = Sth.new 'a', 10
83
+ assert_same sth, sth.each_pair_with_index{}
84
+
85
+ enum = sth.each_pair_with_index
86
+ assert_equal [:name, 'a', 0], enum.next
87
+ assert_equal [:age, 10, 1], enum.next
88
+ assert_raises StopIteration do
89
+ enum.next
90
+ end
91
+ end
92
+
93
93
  end
@@ -1,19 +1,19 @@
1
- require_relative 'helper'
2
-
3
- class Test_Striuct_Subclass_Instance__Freeze < Test::Unit::TestCase
4
-
5
- Sth = Striuct.new :foo
6
-
7
- def test_freeze
8
- sth = Sth.new
9
- sth.freeze
10
-
11
- assert_raises RuntimeError do
12
- sth.foo = 8
13
- end
14
-
15
- assert_equal true, sth.frozen?
16
- end
17
-
18
- end
19
-
1
+ require_relative 'helper'
2
+
3
+ class Test_Striuct_Subclass_Instance__Freeze < Test::Unit::TestCase
4
+
5
+ Sth = Striuct.new :foo
6
+
7
+ def test_freeze
8
+ sth = Sth.new
9
+ sth.freeze
10
+
11
+ assert_raises RuntimeError do
12
+ sth.foo = 8
13
+ end
14
+
15
+ assert_equal true, sth.frozen?
16
+ end
17
+
18
+ end
19
+