striuct 0.6.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![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
|
-
[![Dependency Status](https://gemnasium.com/kachick/striuct.svg)](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
|