striuct 0.4.4.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE.txt +21 -0
  3. data/README.md +45 -62
  4. data/lib/striuct.rb +7 -3
  5. data/lib/striuct/{requirements.rb → bootstrap.rb} +6 -2
  6. data/lib/striuct/classmethods/README.md +2 -2
  7. data/lib/striuct/classmethods/adjustment.rb +77 -13
  8. data/lib/striuct/classmethods/attributes.rb +94 -90
  9. data/lib/striuct/classmethods/conflict_management.rb +109 -106
  10. data/lib/striuct/classmethods/constructor.rb +55 -65
  11. data/lib/striuct/classmethods/copy.rb +45 -43
  12. data/lib/striuct/classmethods/default.rb +23 -21
  13. data/lib/striuct/classmethods/enum.rb +46 -44
  14. data/lib/striuct/classmethods/fix.rb +23 -21
  15. data/lib/striuct/classmethods/hashdeepdupulicatable.rb +15 -15
  16. data/lib/striuct/classmethods/inner.rb +57 -64
  17. data/lib/striuct/classmethods/length.rb +12 -10
  18. data/lib/striuct/classmethods/macro.rb +98 -111
  19. data/lib/striuct/classmethods/names.rb +69 -65
  20. data/lib/striuct/classmethods/predicate.rb +131 -138
  21. data/lib/striuct/classmethods/requirements.rb +2 -2
  22. data/lib/striuct/classmethods/to_struct.rb +21 -18
  23. data/lib/striuct/classmethods/validation.rb +15 -13
  24. data/lib/striuct/instancemethods/README.md +2 -2
  25. data/lib/striuct/instancemethods/assign.rb +29 -27
  26. data/lib/striuct/instancemethods/cast.rb +28 -26
  27. data/lib/striuct/instancemethods/compare.rb +26 -24
  28. data/lib/striuct/instancemethods/default.rb +31 -29
  29. data/lib/striuct/instancemethods/delegate_class_methods.rb +36 -32
  30. data/lib/striuct/instancemethods/enum.rb +86 -84
  31. data/lib/striuct/instancemethods/getter.rb +39 -37
  32. data/lib/striuct/instancemethods/hashy.rb +99 -97
  33. data/lib/striuct/instancemethods/lock.rb +46 -44
  34. data/lib/striuct/instancemethods/object.rb +50 -48
  35. data/lib/striuct/instancemethods/requirements.rb +9 -13
  36. data/lib/striuct/instancemethods/safety.rb +11 -9
  37. data/lib/striuct/instancemethods/setter.rb +46 -49
  38. data/lib/striuct/instancemethods/to_s.rb +39 -37
  39. data/lib/striuct/instancemethods/validation.rb +46 -29
  40. data/lib/striuct/instancemethods/values.rb +52 -33
  41. data/lib/striuct/singleton_class.rb +25 -18
  42. data/lib/striuct/structs.rb +3 -3
  43. metadata +23 -213
  44. data/.gitignore +0 -35
  45. data/.travis.yml +0 -20
  46. data/.yardopts +0 -1
  47. data/Gemfile +0 -11
  48. data/History.old(~0.3.n).rdoc +0 -289
  49. data/MIT-LICENSE +0 -22
  50. data/Rakefile +0 -10
  51. data/benchmark/basics.rb +0 -56
  52. data/example/README.rb +0 -53
  53. data/example/example1.rb +0 -235
  54. data/example/example2.rb +0 -22
  55. data/example/see_trace.rb +0 -32
  56. data/lib/striuct/instancemethods/keyvalidatable.rb +0 -9
  57. data/striuct.gemspec +0 -45
  58. data/test/helper.rb +0 -5
  59. data/test/test_sglc-constructor.rb +0 -36
  60. data/test/test_subc-c-add_members.rb +0 -13
  61. data/test/test_subc-c-close_member.rb +0 -36
  62. data/test/test_subc-c-constructor.rb +0 -92
  63. data/test/test_subc-c-copy.rb +0 -71
  64. data/test/test_subc-c-freeze.rb +0 -36
  65. data/test/test_subc-c-inheritable.rb +0 -58
  66. data/test/test_subc-c-safety_naming.rb +0 -73
  67. data/test/test_subc-f-alias_member.rb +0 -54
  68. data/test/test_subc-f-enum.rb +0 -139
  69. data/test/test_subc-f-predicate.rb +0 -711
  70. data/test/test_subc-f-to_struct.rb +0 -61
  71. data/test/test_subc-f-validation_util.rb +0 -59
  72. data/test/test_subc-f_debug.rb +0 -39
  73. data/test/test_subc-f_name.rb +0 -525
  74. data/test/test_subc-i-accessor.rb +0 -138
  75. data/test/test_subc-i-adjuster.rb +0 -95
  76. data/test/test_subc-i-assign.rb +0 -53
  77. data/test/test_subc-i-basic.rb +0 -32
  78. data/test/test_subc-i-cast.rb +0 -27
  79. data/test/test_subc-i-compare.rb +0 -52
  80. data/test/test_subc-i-copy.rb +0 -23
  81. data/test/test_subc-i-default_value.rb +0 -129
  82. data/test/test_subc-i-freeze.rb +0 -19
  83. data/test/test_subc-i-hashlike.rb +0 -144
  84. data/test/test_subc-i-keyvalidatable.rb +0 -25
  85. data/test/test_subc-i-lock.rb +0 -40
  86. data/test/test_subc-i-must.rb +0 -30
  87. data/test/test_subc-i-to_s_family.rb +0 -26
  88. data/test/test_subc-i-validation_inference.rb +0 -51
  89. data/test/test_subc-i-validation_specific_conditions.rb +0 -297
  90. data/test/test_subc-i-validation_with_getter.rb +0 -33
  91. data/test/test_version.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 746edaaaf527160fde69fb136722ff8861375af7
4
- data.tar.gz: 17062017c2bec73985602a5c4069ffec47acc3f6
2
+ SHA256:
3
+ metadata.gz: d820670e757190ed2db502b8d6e0c53a7689f299262695f3ca18cec69dd5270b
4
+ data.tar.gz: 8a27cca712c9a63c2a5207090a6a8d0d8dcecd24a13bf07fa16c243a3b24c366
5
5
  SHA512:
6
- metadata.gz: 7c3897a36c553fcc2f760581e7b844cb81256e08b774efc4d81ca7ae6d24a811fbb2431a842acd24cd69bafdc045c58ba3ea46674b089eaf639f5acef7a89482
7
- data.tar.gz: 57a64de8a4faa2a740856f770f121f9ade2d924d3a2f99625d2ed3dd369b4f7ddf4a23d8d3e00f2485c9fc82e12dae8038cd37a6df453627c383486a1bd6c6af
6
+ metadata.gz: c90d1e6cc1ac20015660134d88d863dc935d6db44128e0f49f7c807b6b357d4821055d989e9e9e3a8bb4c49382acbab04509bf0445389a454c72c3fb729cbd85
7
+ data.tar.gz: a7154a914174099a8b5d32fe4b534811c14187f3fb9e8735cba701764b7d9aee640de1c276711dcedb85915f33efc9fecac87dde0ae8a09d704d0bbf84f3f11b
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2011 Kenichi Kamiya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,51 +1,40 @@
1
- striuct
2
- =======
1
+ # striuct
3
2
 
4
- [![Build Status](https://secure.travis-ci.org/kachick/striuct.png)](http://travis-ci.org/kachick/striuct)
3
+ ![Build Status](https://github.com/kachick/striuct/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
5
4
  [![Gem Version](https://badge.fury.io/rb/striuct.png)](http://badge.fury.io/rb/striuct)
6
5
 
7
- Description
8
- -----------
9
-
10
6
  Struct++
11
7
 
12
- Features
13
- --------
8
+ ## Usage
14
9
 
15
- ### Strict
10
+ Require Ruby 2.6 or later
16
11
 
17
- * Easy and Flexible Validations
18
- * Prevent to conflict member names
19
- * Lock setters for each member
12
+ Add this line to your `Gemfile`
20
13
 
21
- ### Useful
22
-
23
- * Hook just before setters
24
- * Default value
25
- * Member aliasing
26
- * Inheritable
27
- * Handling between nil <-> unassigned
28
- * More flendly API for Hash
14
+ ```ruby
15
+ gem 'striuct', '>= 0.8.0', '< 0.9.0'
16
+ ```
29
17
 
30
- ### Onepoint
18
+ Then add below code into your Ruby code
31
19
 
32
- * Base API looks like Struct
33
- * Pure Ruby :)
20
+ ```ruby
21
+ require 'striuct'
22
+ ```
34
23
 
35
- Usage
36
- -----
24
+ ### Overview
37
25
 
38
- ### Overview - Case 1
26
+ #### Case 1
39
27
 
40
28
  ```ruby
41
29
  require 'striuct'
42
30
 
43
31
  class Person < Striuct
44
- member :fullname, AND(String, /\A.+\z/) # Flexible Validation
45
- alias_member :name, :fullname # Use other name
32
+ member :full_name, AND(String, /\A.+\z/) # Flexible Validation
33
+ alias_member :name, :full_name # Use other name
46
34
  end
47
35
 
48
- class User < Person # Inheritable
36
+ # Inheritable
37
+ class User < Person
49
38
  member :id, Integer, # Looks typed validation
50
39
  default_proc: ->{User.next_id} # With default value
51
40
 
@@ -56,26 +45,26 @@ class User < Person # Inheritable
56
45
  end
57
46
 
58
47
  john = User.new 'john'
59
- john[:name] #=> 'john'
48
+ john[:name] #=> 'john'
60
49
  john.name = '' #=> Exception # Validate with setter
61
50
  john.id #=> 1
62
51
  ken = User[name: 'ken'] # Construct from hash
63
52
  ken.id #=> 2
64
53
  ```
65
- ### Overview - Case 2
54
+
55
+ #### Case 2
66
56
 
67
57
  ```ruby
68
58
  class Foo < Striuct
69
59
  member :foo
70
- member :bar, Numeric, # First validation under Numeric
71
- inference: true # And use inference Validation
60
+ member :bar, Numeric
72
61
  member :with_adjuster, Integer,
73
62
  &->v{Integer v} # Use adjuster before a setter
74
63
  end
75
64
 
76
65
  foo = Foo.new
77
66
 
78
- # nil <-> unaasigned
67
+ # nil <-> unassigned
79
68
  foo.foo #=> nil
80
69
  foo.assigned?(:foo) #=> false
81
70
  foo.foo = nil
@@ -85,7 +74,6 @@ foo.assigned?(:foo) #=> true
85
74
  foo.lock(:foo)
86
75
  foo.foo = nil #=> error
87
76
 
88
- # Inference Validation
89
77
  foo.bar = 1.2 #=> pass # memorize 1.2's class is Float
90
78
  foo.bar = 1 #=> error # 1 is not Float
91
79
 
@@ -94,7 +82,7 @@ foo.with_adjuster = '5'
94
82
  foo.with_adjuster #=> 5 # Casted via adjuster
95
83
  ```
96
84
 
97
- ### Overview - Case 3
85
+ #### Case 3
98
86
 
99
87
  ```ruby
100
88
  class UseMustOption < Striuct
@@ -104,37 +92,32 @@ end
104
92
  UseMustOption.new #=> InvalidOperationError "`foo` require a value under `must` option "
105
93
  ```
106
94
 
95
+ ## Features
107
96
 
108
- ### How to build flexible conditions ?
109
-
110
- * That from validation library.
111
- See the [validation-API](http://kachick.github.com/validation/yard/frames.html)
112
-
113
- Requirements
114
- -------------
97
+ ### Strict
115
98
 
116
- * Ruby - [1.9.2 or later](http://travis-ci.org/#!/kachick/striuct)
99
+ * Easy and Flexible Validations
100
+ * Basically use `#===` for the validation
101
+ * The pattern builder DSL is just using [eqq](https://github.com/kachick/eqq)
102
+ * When passed the Proc, it will be evaluated in the instance context
103
+ * Prevent to conflict member names
104
+ * Lock setters for each member
117
105
 
118
- Install
119
- -------
106
+ ### Useful
120
107
 
121
- ```bash
122
- gem install striuct
123
- ```
108
+ * Hook just before setters
109
+ * Default value
110
+ * Member aliasing
111
+ * Inheritable
112
+ * Handling between nil <-> unassigned
113
+ * Similar API for Hash
124
114
 
125
- Link
126
- ----
115
+ ### Finally
127
116
 
128
- * [code](https://github.com/kachick/striuct)
129
- * [wiki](https://github.com/kachick/striuct/wiki)
130
- * [API](http://kachick.github.com/striuct/yard/frames.html)
131
- * [issues](https://github.com/kachick/striuct/issues)
132
- * [CI](http://travis-ci.org/#!/kachick/striuct)
133
- * [gem](https://rubygems.org/gems/striuct)
117
+ * Base API looks like Struct
118
+ * Pure Ruby :)
134
119
 
135
- License
136
- --------
120
+ ## Link
137
121
 
138
- The MIT X11 License
139
- Copyright (c) 2011 Kenichi Kamiya
140
- See MIT-LICENSE for further details.
122
+ * [Repository](https://github.com/kachick/striuct)
123
+ * [API documents](https://kachick.github.io/striuct/)
data/lib/striuct.rb CHANGED
@@ -1,12 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # striuct - Struct++
2
4
  # Copyright (c) 2011-2012 Kenichi Kamiya
3
5
 
4
6
  # @abstract
5
7
  class Striuct
6
-
7
8
  class Error < StandardError; end
8
9
  class InvalidOperationError < Error; end
9
-
10
+ class InvalidValueError < Error; end
11
+ class InvalidWritingError < InvalidValueError; end
12
+ class InvalidReadingError < InvalidValueError; end
13
+ class InvalidAdjustingError < InvalidValueError; end
10
14
  end
11
15
 
12
- require_relative 'striuct/requirements'
16
+ require_relative 'striuct/bootstrap'
@@ -1,5 +1,9 @@
1
- require 'validation'
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'eqq'
5
+
2
6
  require_relative 'structs'
3
7
  require_relative 'classmethods/requirements'
4
8
  require_relative 'instancemethods/requirements'
5
- require_relative 'singleton_class'
9
+ require_relative 'singleton_class'
@@ -1,10 +1,10 @@
1
1
  Note
2
2
  =====
3
3
 
4
- This dir's tree is diveded under roles/features.
4
+ This dir's tree is divided under roles/features.
5
5
  Not only divided by CONSTANT names.
6
6
 
7
7
  CONSTANT
8
8
  --------
9
9
 
10
- * attributes - Attributes
10
+ * attributes - Attributes
@@ -1,15 +1,79 @@
1
- class Striuct; module ClassMethods
2
-
3
- # @group Adjuster
4
-
5
- # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
6
- def adjuster_for(key)
7
- autonym = autonym_for_key key
8
- raise KeyError unless with_adjuster? autonym
9
-
10
- _attributes_for(autonym).adjuster
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ class Striuct
4
+ module ClassMethods
5
+ # @group Adjuster
6
+
7
+ # Adjuster Builders
8
+ # Apply adjuster when passed pattern.
9
+ # @param pattern [Proc, Method, #===]
10
+ # @param adjuster [Proc, #to_proc]
11
+ # @return [Proc]
12
+ def WHEN(pattern, adjuster)
13
+ unless Eqq.valid?(pattern)
14
+ raise ArgumentError, 'wrong object for pattern'
15
+ end
16
+
17
+ unless Striuct.adjustable?(adjuster)
18
+ raise ArgumentError, 'wrong object for adjuster'
19
+ end
20
+
21
+ ->v { _valid?(pattern, v) ? adjuster.call(v) : v }
22
+ end
23
+
24
+ # Sequential apply all adjusters.
25
+ # @param adjuster1 [Proc, #to_proc]
26
+ # @param adjuster2 [Proc, #to_proc]
27
+ # @param adjusters [Proc, #to_proc]
28
+ # @return [Proc]
29
+ def INJECT(adjuster1, adjuster2, *adjusters)
30
+ adjusters = [adjuster1, adjuster2, *adjusters]
12
31
 
13
- # @endgroup
32
+ unless adjusters.all? { |f| adjustable?(f) }
33
+ raise ArgumentError, 'wrong object for adjuster'
34
+ end
14
35
 
15
- end; end
36
+ ->v {
37
+ adjusters.reduce(v) { |ret, adjuster| adjuster.call(ret) }
38
+ }
39
+ end
40
+
41
+ # Accept any parser when that respond to parse method.
42
+ # @param parser [#parse]
43
+ # @return [Proc]
44
+ def PARSE(parser)
45
+ if !::Integer.equal?(parser) && !parser.respond_to?(:parse)
46
+ raise ArgumentError, 'wrong object for parser'
47
+ end
48
+
49
+ ->v {
50
+ if ::Integer.equal?(parser)
51
+ ::Kernel.Integer(v)
52
+ else
53
+ parser.parse(
54
+ case v
55
+ when String
56
+ v
57
+ when ->_ { v.respond_to?(:to_str) }
58
+ v.to_str
59
+ when ->_ { v.respond_to?(:read) }
60
+ v.read
61
+ else
62
+ raise TypeError, 'wrong object for parsing source'
63
+ end
64
+ )
65
+ end
66
+ }
67
+ end
68
+
69
+ # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
70
+ def adjuster_for(key)
71
+ autonym = autonym_for_key(key)
72
+ raise KeyError unless with_adjuster?(autonym)
73
+
74
+ _attributes_for(autonym).adjuster
75
+ end
76
+
77
+ # @endgroup
78
+ end
79
+ end
@@ -1,112 +1,116 @@
1
- class Striuct; module ClassMethods
2
-
3
- # Attributes for autonym of each member
4
- class Attributes
5
-
6
- VALUES = [ :condition,
7
- :adjuster ].freeze
8
-
9
- BOOLEANS = [ :inference,
10
- :must,
11
- :safety_setter,
12
- :safety_getter ].freeze
13
-
14
- def initialize
15
- @hash = { inference: false,
16
- must: false,
17
- safety_setter: false,
18
- safety_getter: false }
19
- end
20
-
21
- VALUES.each do |role|
22
- define_method :"with_#{role}?" do
23
- @hash.has_key? role
1
+ # frozen_string_literal: true
2
+
3
+ class Striuct
4
+ module ClassMethods
5
+ # Attributes for autonym of each member
6
+ class Attributes
7
+ VALUES = [:condition,
8
+ :adjuster].freeze
9
+
10
+ BOOLEANS = [
11
+ :must,
12
+ :safety_setter,
13
+ :safety_getter
14
+ ].freeze
15
+
16
+ def initialize
17
+ @hash = {
18
+ must: false,
19
+ safety_setter: false,
20
+ safety_getter: false
21
+ }
24
22
  end
25
-
26
- define_method role do
27
- @hash.fetch role
23
+
24
+ VALUES.each do |role|
25
+ define_method :"with_#{role}?" do
26
+ @hash.key?(role)
27
+ end
28
+
29
+ define_method role do
30
+ @hash.fetch(role)
31
+ end
28
32
  end
29
- end
30
33
 
31
- def condition=(condition)
32
- unless ::Validation.conditionable? condition
33
- raise TypeError, 'wrong object for condition'
34
+ def condition=(condition)
35
+ unless Eqq.valid?(condition)
36
+ raise TypeError, 'wrong object for condition'
37
+ end
38
+
39
+ @hash[:condition] = condition
34
40
  end
35
41
 
36
- @hash[:condition] = condition
37
- end
42
+ def adjuster=(adjuster)
43
+ unless Striuct.adjustable?(adjuster)
44
+ raise ArgumentError, 'wrong object for adjuster'
45
+ end
38
46
 
39
- def adjuster=(adjuster)
40
- unless ::Validation.adjustable? adjuster
41
- raise ArgumentError, 'wrong object for adjuster'
47
+ @hash[:adjuster] = adjuster
42
48
  end
43
49
 
44
- @hash[:adjuster] = adjuster
45
- end
50
+ BOOLEANS.each do |role|
51
+ define_method :"with_#{role}?" do
52
+ @hash.fetch(role)
53
+ end
54
+
55
+ define_method :"#{role}=" do |arg|
56
+ raise TypeError unless arg.equal?(true) || arg.equal?(false)
46
57
 
47
- BOOLEANS.each do |role|
48
- define_method :"with_#{role}?" do
49
- @hash.fetch role
58
+ @hash[role] = arg
59
+ end
50
60
  end
51
-
52
- define_method :"#{role}=" do |arg|
53
- raise TypeError unless arg.equal?(true) or arg.equal?(false)
54
61
 
55
- @hash[role] = arg
56
- end
57
- end
62
+ def with_default?
63
+ @hash.key?(:default_value)
64
+ end
58
65
 
59
- def with_default?
60
- @hash.has_key? :default_value
61
- end
66
+ def default_value
67
+ @hash.fetch(:default_value)
68
+ end
62
69
 
63
- def default_value
64
- @hash.fetch :default_value
65
- end
70
+ def default_type
71
+ @hash.fetch(:default_type)
72
+ end
66
73
 
67
- def default_type
68
- @hash.fetch :default_type
69
- end
74
+ # @param [Symbol] type - :value / :lazy
75
+ def set_default(value, type)
76
+ raise TypeError unless type.equal?(:value) || type.equal?(:lazy)
70
77
 
71
- # @param [Symbol] type - :value / :lazy
72
- def set_default(value, type)
73
- raise TypeError unless type.equal?(:value) or type.equal?(:lazy)
74
- check_default_lazy_proc value if type.equal?(:lazy)
75
-
76
- @hash[:default_type] = type
77
- @hash[:default_value] = value
78
- end
78
+ check_default_lazy_proc(value) if type.equal?(:lazy)
79
79
 
80
- def check_default_lazy_proc(_proc)
81
- raise TypeError unless _proc.respond_to? :call
82
- arity = _proc.arity
83
- unless arity <= 2
84
- raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
80
+ @hash[:default_type] = type
81
+ @hash[:default_value] = value
85
82
  end
86
- end
87
83
 
88
- def freeze
89
- ret = super
90
- @hash.freeze
91
- ret
92
- end
84
+ def check_default_lazy_proc(proc)
85
+ raise TypeError unless proc.respond_to?(:call)
93
86
 
94
- def dup
95
- ret = super
96
- @hash = @hash.dup
97
- ret
98
- end
99
-
100
- private
101
-
102
- def initialize_copy(original)
103
- ret = super original
104
- @hash = @hash.dup
105
- ret
106
- end
87
+ arity = proc.arity
88
+ unless arity <= 2
89
+ raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
90
+ end
91
+ end
107
92
 
108
- end
93
+ def freeze
94
+ ret = super
95
+ @hash.freeze
96
+ ret
97
+ end
98
+
99
+ def dup
100
+ ret = super
101
+ @hash = @hash.dup
102
+ ret
103
+ end
109
104
 
110
- private_constant :Attributes
105
+ private
111
106
 
112
- end; end
107
+ def initialize_copy(original)
108
+ ret = super(original)
109
+ @hash = @hash.dup
110
+ ret
111
+ end
112
+ end
113
+
114
+ private_constant :Attributes
115
+ end
116
+ end