striuct 0.4.4.1 → 0.8.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.
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