striuct 0.6.1 → 0.9.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/MIT-LICENSE.txt +21 -0
- data/README.md +44 -60
- data/lib/striuct/{requirements.rb → bootstrap.rb} +6 -2
- data/lib/striuct/classmethods/README.md +2 -2
- data/lib/striuct/classmethods/adjustment.rb +77 -13
- data/lib/striuct/classmethods/attributes.rb +94 -92
- data/lib/striuct/classmethods/conflict_management.rb +109 -106
- data/lib/striuct/classmethods/constructor.rb +55 -65
- data/lib/striuct/classmethods/copy.rb +45 -43
- data/lib/striuct/classmethods/default.rb +23 -21
- data/lib/striuct/classmethods/enum.rb +46 -44
- data/lib/striuct/classmethods/fix.rb +23 -21
- data/lib/striuct/classmethods/hashdeepdupulicatable.rb +15 -15
- data/lib/striuct/classmethods/inner.rb +57 -55
- data/lib/striuct/classmethods/length.rb +12 -10
- data/lib/striuct/classmethods/macro.rb +99 -106
- data/lib/striuct/classmethods/names.rb +69 -65
- data/lib/striuct/classmethods/predicate.rb +131 -129
- data/lib/striuct/classmethods/requirements.rb +2 -2
- data/lib/striuct/classmethods/to_struct.rb +21 -18
- data/lib/striuct/classmethods/validation.rb +15 -13
- data/lib/striuct/instancemethods/README.md +2 -2
- data/lib/striuct/instancemethods/assign.rb +29 -27
- data/lib/striuct/instancemethods/cast.rb +28 -26
- data/lib/striuct/instancemethods/compare.rb +26 -24
- data/lib/striuct/instancemethods/default.rb +31 -29
- data/lib/striuct/instancemethods/delegate_class_methods.rb +35 -33
- data/lib/striuct/instancemethods/enum.rb +86 -84
- data/lib/striuct/instancemethods/getter.rb +39 -37
- data/lib/striuct/instancemethods/hashy.rb +99 -97
- data/lib/striuct/instancemethods/lock.rb +46 -44
- data/lib/striuct/instancemethods/object.rb +50 -48
- data/lib/striuct/instancemethods/requirements.rb +9 -13
- data/lib/striuct/instancemethods/safety.rb +11 -9
- data/lib/striuct/instancemethods/setter.rb +46 -45
- data/lib/striuct/instancemethods/to_s.rb +39 -37
- data/lib/striuct/instancemethods/validation.rb +46 -29
- data/lib/striuct/instancemethods/values.rb +50 -48
- data/lib/striuct/singleton_class.rb +25 -18
- data/lib/striuct/structs.rb +3 -3
- data/lib/striuct.rb +7 -3
- metadata +18 -209
- data/.gitignore +0 -35
- data/.travis.yml +0 -17
- data/.yardopts +0 -1
- data/Gemfile +0 -11
- data/MIT-LICENSE +0 -22
- data/Rakefile +0 -11
- data/benchmark/basics.rb +0 -56
- data/example/README.rb +0 -50
- data/example/example1.rb +0 -195
- data/example/example2.rb +0 -20
- data/example/see_trace.rb +0 -32
- data/lib/striuct/instancemethods/keyvalidatable.rb +0 -9
- data/striuct.gemspec +0 -45
- data/test/helper.rb +0 -3
- data/test/test_sglc-constructor.rb +0 -36
- data/test/test_subc-c-add_members.rb +0 -13
- data/test/test_subc-c-close_member.rb +0 -36
- data/test/test_subc-c-constructor.rb +0 -92
- data/test/test_subc-c-copy.rb +0 -71
- data/test/test_subc-c-freeze.rb +0 -36
- data/test/test_subc-c-inheritable.rb +0 -58
- data/test/test_subc-c-safety_naming.rb +0 -73
- data/test/test_subc-f-alias_member.rb +0 -54
- data/test/test_subc-f-enum.rb +0 -159
- data/test/test_subc-f-predicate.rb +0 -647
- data/test/test_subc-f-to_struct.rb +0 -61
- data/test/test_subc-f-validation_util.rb +0 -59
- data/test/test_subc-f_debug.rb +0 -39
- data/test/test_subc-f_name.rb +0 -525
- data/test/test_subc-i-accessor.rb +0 -138
- data/test/test_subc-i-adjuster.rb +0 -95
- data/test/test_subc-i-assign.rb +0 -53
- data/test/test_subc-i-basic.rb +0 -43
- data/test/test_subc-i-cast.rb +0 -27
- data/test/test_subc-i-compare.rb +0 -52
- data/test/test_subc-i-copy.rb +0 -23
- data/test/test_subc-i-default_value.rb +0 -129
- data/test/test_subc-i-freeze.rb +0 -19
- data/test/test_subc-i-hashlike.rb +0 -144
- data/test/test_subc-i-keyvalidatable.rb +0 -25
- data/test/test_subc-i-lock.rb +0 -40
- data/test/test_subc-i-must.rb +0 -30
- data/test/test_subc-i-to_s_family.rb +0 -26
- data/test/test_subc-i-validation_specific_conditions.rb +0 -297
- data/test/test_subc-i-validation_with_getter.rb +0 -33
- data/test/test_version.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a14fe7f8c251b39c9e7a8d65fc96b62519a6e271eb5765b043f92cfe1b8bc3b
|
4
|
+
data.tar.gz: be0b9456cee901dc7d0079e5661de91cda71b52cdae47fa1277cd7b833310126
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7600df197c958a8fc6f37cfec1f0bff19ec3c1542f469ed12f927193f060c8e1a4c211d6c0d3411d344e9562714b7c8cf159469409c4635d0018abd5c855bcd
|
7
|
+
data.tar.gz: 03b8604868221c485c16c99ce1e428da36f2c5f9db6c0458957f460f0a16aaba55753043cb65901df1f695fc5c9bf069d0b09dae9aa88f50081200844d3ca9c1
|
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,52 +1,40 @@
|
|
1
|
-
striuct
|
2
|
-
=======
|
1
|
+
# striuct
|
3
2
|
|
4
|
-
|
3
|
+

|
5
4
|
[](http://badge.fury.io/rb/striuct)
|
6
|
-
[](https://gemnasium.com/kachick/striuct)
|
7
|
-
|
8
|
-
Description
|
9
|
-
-----------
|
10
5
|
|
11
6
|
Struct++
|
12
7
|
|
13
|
-
|
14
|
-
--------
|
8
|
+
## Usage
|
15
9
|
|
16
|
-
|
10
|
+
Require Ruby 2.6 or later
|
17
11
|
|
18
|
-
|
19
|
-
* Prevent to conflict member names
|
20
|
-
* Lock setters for each member
|
12
|
+
Add this line to your `Gemfile`
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
* Default value
|
26
|
-
* Member aliasing
|
27
|
-
* Inheritable
|
28
|
-
* Handling between nil <-> unassigned
|
29
|
-
* More flendly API for Hash
|
14
|
+
```ruby
|
15
|
+
gem 'striuct', '~> 0.9.0'
|
16
|
+
```
|
30
17
|
|
31
|
-
|
18
|
+
Then add below code into your Ruby code
|
32
19
|
|
33
|
-
|
34
|
-
|
20
|
+
```ruby
|
21
|
+
require 'striuct'
|
22
|
+
```
|
35
23
|
|
36
|
-
|
37
|
-
-----
|
24
|
+
### Overview
|
38
25
|
|
39
|
-
|
26
|
+
#### Case 1
|
40
27
|
|
41
28
|
```ruby
|
42
29
|
require 'striuct'
|
43
30
|
|
44
31
|
class Person < Striuct
|
45
|
-
member :
|
46
|
-
alias_member :name, :
|
32
|
+
member :full_name, AND(String, /\A.+\z/) # Flexible Validation
|
33
|
+
alias_member :name, :full_name # Use other name
|
47
34
|
end
|
48
35
|
|
49
|
-
|
36
|
+
# Inheritable
|
37
|
+
class User < Person
|
50
38
|
member :id, Integer, # Looks typed validation
|
51
39
|
default_proc: ->{User.next_id} # With default value
|
52
40
|
|
@@ -57,13 +45,14 @@ class User < Person # Inheritable
|
|
57
45
|
end
|
58
46
|
|
59
47
|
john = User.new 'john'
|
60
|
-
john[:name] #=> 'john'
|
48
|
+
john[:name] #=> 'john'
|
61
49
|
john.name = '' #=> Exception # Validate with setter
|
62
50
|
john.id #=> 1
|
63
51
|
ken = User[name: 'ken'] # Construct from hash
|
64
52
|
ken.id #=> 2
|
65
53
|
```
|
66
|
-
|
54
|
+
|
55
|
+
#### Case 2
|
67
56
|
|
68
57
|
```ruby
|
69
58
|
class Foo < Striuct
|
@@ -75,7 +64,7 @@ end
|
|
75
64
|
|
76
65
|
foo = Foo.new
|
77
66
|
|
78
|
-
# nil <->
|
67
|
+
# nil <-> unassigned
|
79
68
|
foo.foo #=> nil
|
80
69
|
foo.assigned?(:foo) #=> false
|
81
70
|
foo.foo = nil
|
@@ -93,7 +82,7 @@ foo.with_adjuster = '5'
|
|
93
82
|
foo.with_adjuster #=> 5 # Casted via adjuster
|
94
83
|
```
|
95
84
|
|
96
|
-
|
85
|
+
#### Case 3
|
97
86
|
|
98
87
|
```ruby
|
99
88
|
class UseMustOption < Striuct
|
@@ -103,37 +92,32 @@ end
|
|
103
92
|
UseMustOption.new #=> InvalidOperationError "`foo` require a value under `must` option "
|
104
93
|
```
|
105
94
|
|
95
|
+
## Features
|
106
96
|
|
107
|
-
###
|
108
|
-
|
109
|
-
* That from validation library.
|
110
|
-
See the [validation-API](http://kachick.github.com/validation/yard/frames.html)
|
111
|
-
|
112
|
-
Requirements
|
113
|
-
-------------
|
97
|
+
### Strict
|
114
98
|
|
115
|
-
*
|
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
|
116
105
|
|
117
|
-
|
118
|
-
-------
|
106
|
+
### Useful
|
119
107
|
|
120
|
-
|
121
|
-
|
122
|
-
|
108
|
+
* Hook just before setters
|
109
|
+
* Default value
|
110
|
+
* Member aliasing
|
111
|
+
* Inheritable
|
112
|
+
* Handling between nil <-> unassigned
|
113
|
+
* Similar API for Hash
|
123
114
|
|
124
|
-
|
125
|
-
----
|
115
|
+
### Finally
|
126
116
|
|
127
|
-
*
|
128
|
-
*
|
129
|
-
* [API](http://www.rubydoc.info/github/kachick/striuct)
|
130
|
-
* [Issues](https://github.com/kachick/striuct/issues)
|
131
|
-
* [CI](http://travis-ci.org/#!/kachick/striuct)
|
132
|
-
* [gem](https://rubygems.org/gems/striuct)
|
117
|
+
* Base API looks like Struct
|
118
|
+
* Pure Ruby :)
|
133
119
|
|
134
|
-
|
135
|
-
--------
|
120
|
+
## Link
|
136
121
|
|
137
|
-
|
138
|
-
|
139
|
-
See MIT-LICENSE for further details.
|
122
|
+
* [Repository](https://github.com/kachick/striuct)
|
123
|
+
* [API documents](https://kachick.github.io/striuct/)
|
@@ -1,5 +1,9 @@
|
|
1
|
-
|
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,15 +1,79 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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.pattern?(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
|
-
|
32
|
+
unless adjusters.all? { |f| adjustable?(f) }
|
33
|
+
raise ArgumentError, 'wrong object for adjuster'
|
34
|
+
end
|
14
35
|
|
15
|
-
|
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,114 +1,116 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
VALUES.each do |role|
|
24
|
-
define_method :"with_#{role}?" do
|
25
|
-
@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
|
+
}
|
26
22
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
32
|
end
|
31
|
-
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def condition=(condition)
|
35
|
+
unless Eqq.pattern?(condition)
|
36
|
+
raise TypeError, 'wrong object for condition'
|
37
|
+
end
|
38
|
+
|
39
|
+
@hash[:condition] = condition
|
36
40
|
end
|
37
41
|
|
38
|
-
|
39
|
-
|
42
|
+
def adjuster=(adjuster)
|
43
|
+
unless Striuct.adjustable?(adjuster)
|
44
|
+
raise ArgumentError, 'wrong object for adjuster'
|
45
|
+
end
|
40
46
|
|
41
|
-
|
42
|
-
unless ::Validation.adjustable? adjuster
|
43
|
-
raise ArgumentError, 'wrong object for adjuster'
|
47
|
+
@hash[:adjuster] = adjuster
|
44
48
|
end
|
45
49
|
|
46
|
-
|
47
|
-
|
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)
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
@hash.fetch role
|
58
|
+
@hash[role] = arg
|
59
|
+
end
|
52
60
|
end
|
53
|
-
|
54
|
-
define_method :"#{role}=" do |arg|
|
55
|
-
raise TypeError unless arg.equal?(true) or arg.equal?(false)
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
def with_default?
|
63
|
+
@hash.key?(:default_value)
|
64
|
+
end
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
def default_value
|
67
|
+
@hash.fetch(:default_value)
|
68
|
+
end
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
def default_type
|
71
|
+
@hash.fetch(:default_type)
|
72
|
+
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
# @param [Symbol] type - :value / :lazy
|
75
|
+
def set_default(value, type)
|
76
|
+
raise TypeError unless type.equal?(:value) || type.equal?(:lazy)
|
72
77
|
|
73
|
-
|
74
|
-
def set_default(value, type)
|
75
|
-
raise TypeError unless type.equal?(:value) or type.equal?(:lazy)
|
76
|
-
check_default_lazy_proc value if type.equal?(:lazy)
|
77
|
-
|
78
|
-
@hash[:default_type] = type
|
79
|
-
@hash[:default_value] = value
|
80
|
-
end
|
78
|
+
check_default_lazy_proc(value) if type.equal?(:lazy)
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
arity = _proc.arity
|
85
|
-
unless arity <= 2
|
86
|
-
raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
|
80
|
+
@hash[:default_type] = type
|
81
|
+
@hash[:default_value] = value
|
87
82
|
end
|
88
|
-
end
|
89
83
|
|
90
|
-
|
91
|
-
|
92
|
-
@hash.freeze
|
93
|
-
ret
|
94
|
-
end
|
84
|
+
def check_default_lazy_proc(proc)
|
85
|
+
raise TypeError unless proc.respond_to?(:call)
|
95
86
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def initialize_copy(original)
|
105
|
-
ret = super original
|
106
|
-
@hash = @hash.dup
|
107
|
-
ret
|
108
|
-
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
|
109
92
|
|
110
|
-
|
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
|
111
104
|
|
112
|
-
|
105
|
+
private
|
113
106
|
|
114
|
-
|
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
|