chef 12.15.19-universal-mingw32 → 12.16.42-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/VERSION +1 -1
- data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +3 -1
- data/acceptance/Gemfile.lock +14 -14
- data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +3 -11
- data/distro/common/html/knife_bootstrap.html +1 -1
- data/distro/common/man/man1/README.md +2 -2
- data/distro/common/man/man1/knife-client.1 +1 -1
- data/lib/chef/application.rb +7 -15
- data/lib/chef/application/client.rb +2 -2
- data/lib/chef/application/solo.rb +1 -1
- data/lib/chef/chef_class.rb +1 -0
- data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +3 -7
- data/lib/chef/chef_fs/file_system/chef_server/versioned_cookbook_dir.rb +1 -1
- data/lib/chef/data_collector.rb +83 -9
- data/lib/chef/data_collector/messages.rb +2 -1
- data/lib/chef/dsl/core.rb +1 -1
- data/lib/chef/dsl/declare_resource.rb +10 -4
- data/lib/chef/dsl/method_missing.rb +1 -1
- data/lib/chef/dsl/recipe.rb +1 -1
- data/lib/chef/dsl/universal.rb +1 -1
- data/lib/chef/event_dispatch/base.rb +3 -0
- data/lib/chef/http.rb +3 -4
- data/lib/chef/knife.rb +20 -2
- data/lib/chef/knife/core/generic_presenter.rb +18 -4
- data/lib/chef/knife/node_show.rb +0 -5
- data/lib/chef/knife/osc_user_show.rb +0 -1
- data/lib/chef/knife/ssl_fetch.rb +9 -5
- data/lib/chef/mixin/powershell_out.rb +1 -1
- data/lib/chef/mixin/shell_out.rb +1 -1
- data/lib/chef/node.rb +1 -5
- data/lib/chef/node/attribute.rb +70 -98
- data/lib/chef/node/attribute_collections.rb +28 -19
- data/lib/chef/node/common_api.rb +0 -6
- data/lib/chef/node/immutable_collections.rb +16 -79
- data/lib/chef/node/mixin/deep_merge_cache.rb +61 -0
- data/lib/chef/node/mixin/immutablize_array.rb +67 -0
- data/lib/chef/node/mixin/immutablize_hash.rb +54 -0
- data/lib/chef/node/mixin/state_tracking.rb +93 -0
- data/lib/chef/property.rb +4 -4
- data/lib/chef/provider/cron.rb +1 -1
- data/lib/chef/provider/group/suse.rb +23 -4
- data/lib/chef/provider/package.rb +43 -5
- data/lib/chef/provider/package/apt.rb +20 -0
- data/lib/chef/provider/package/windows/exe.rb +4 -3
- data/lib/chef/provider/package/windows/msi.rb +4 -3
- data/lib/chef/provider/package/yum.rb +20 -0
- data/lib/chef/provider/package/zypper.rb +20 -0
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service/upstart.rb +25 -9
- data/lib/chef/provider/user.rb +4 -6
- data/lib/chef/provider/user/dscl.rb +8 -3
- data/lib/chef/provider/user/solaris.rb +5 -12
- data/lib/chef/resource.rb +19 -0
- data/lib/chef/resource/file.rb +1 -1
- data/lib/chef/resource/package.rb +1 -1
- data/lib/chef/resource/scm.rb +1 -7
- data/lib/chef/resource/yum_repository.rb +1 -1
- data/lib/chef/rest.rb +1 -0
- data/lib/chef/run_context.rb +12 -0
- data/lib/chef/version.rb +1 -1
- data/spec/data/trusted_certs/example_no_cn.crt +36 -0
- data/spec/functional/resource/group_spec.rb +1 -0
- data/spec/functional/resource/user/useradd_spec.rb +4 -2
- data/spec/integration/knife/data_bag_create_spec.rb +0 -3
- data/spec/integration/knife/environment_show_spec.rb +24 -4
- data/spec/integration/knife/node_environment_set_spec.rb +4 -1
- data/spec/integration/recipes/accumulator_spec.rb +232 -0
- data/spec/integration/recipes/resource_action_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/shared/context/client.rb +12 -3
- data/spec/support/shared/integration/app_server_support.rb +1 -1
- data/spec/support/shared/integration/knife_support.rb +4 -1
- data/spec/unit/data_collector/messages_spec.rb +2 -0
- data/spec/unit/data_collector_spec.rb +158 -21
- data/spec/unit/http_spec.rb +1 -1
- data/spec/unit/knife/core/gem_glob_loader_spec.rb +1 -1
- data/spec/unit/knife/core/ui_spec.rb +10 -0
- data/spec/unit/knife/ssl_fetch_spec.rb +38 -0
- data/spec/unit/knife_spec.rb +31 -0
- data/spec/unit/mixin/powershell_out_spec.rb +25 -1
- data/spec/unit/node/attribute_spec.rb +46 -1
- data/spec/unit/node/vivid_mash_spec.rb +27 -89
- data/spec/unit/node_spec.rb +134 -3
- data/spec/unit/provider/deploy_spec.rb +1 -1
- data/spec/unit/provider/group/suse_spec.rb +90 -0
- data/spec/unit/provider/package/apt_spec.rb +22 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +13 -4
- data/spec/unit/provider/package/windows_spec.rb +3 -3
- data/spec/unit/provider/package/yum_spec.rb +18 -0
- data/spec/unit/provider/package/zypper_spec.rb +64 -0
- data/spec/unit/provider/package_spec.rb +58 -0
- data/spec/unit/provider/remote_file/content_spec.rb +1 -1
- data/spec/unit/provider/service/upstart_service_spec.rb +13 -6
- data/spec/unit/provider/user/solaris_spec.rb +36 -9
- data/spec/unit/provider/user_spec.rb +6 -0
- data/spec/unit/resource/apt_repository_spec.rb +1 -1
- metadata +12 -5
@@ -17,6 +17,7 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require "chef/node/common_api"
|
20
|
+
require "chef/node/mixin/state_tracking"
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Node
|
@@ -33,7 +34,6 @@ class Chef
|
|
33
34
|
:compact!,
|
34
35
|
:default=,
|
35
36
|
:default_proc=,
|
36
|
-
:delete,
|
37
37
|
:delete_at,
|
38
38
|
:delete_if,
|
39
39
|
:fill,
|
@@ -63,15 +63,17 @@ class Chef
|
|
63
63
|
MUTATOR_METHODS.each do |mutator|
|
64
64
|
define_method(mutator) do |*args, &block|
|
65
65
|
ret = super(*args, &block)
|
66
|
-
|
66
|
+
send_reset_cache
|
67
67
|
ret
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
def delete(key, &block)
|
72
|
+
send_reset_cache(__path__, key)
|
73
|
+
super
|
74
|
+
end
|
72
75
|
|
73
|
-
def initialize(
|
74
|
-
@root = root
|
76
|
+
def initialize(data = [])
|
75
77
|
super(data)
|
76
78
|
map! { |e| convert_value(e) }
|
77
79
|
end
|
@@ -96,14 +98,20 @@ class Chef
|
|
96
98
|
when AttrArray
|
97
99
|
value
|
98
100
|
when Hash
|
99
|
-
VividMash.new(
|
101
|
+
VividMash.new(value, __root__, __node__, __precedence__)
|
100
102
|
when Array
|
101
|
-
AttrArray.new(
|
103
|
+
AttrArray.new(value, __root__, __node__, __precedence__)
|
102
104
|
else
|
103
105
|
value
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
109
|
+
# needed for __path__
|
110
|
+
def convert_key(key)
|
111
|
+
key
|
112
|
+
end
|
113
|
+
|
114
|
+
prepend Chef::Node::Mixin::StateTracking
|
107
115
|
end
|
108
116
|
|
109
117
|
# == VividMash
|
@@ -117,8 +125,6 @@ class Chef
|
|
117
125
|
# #fetch, work as normal).
|
118
126
|
# * attr_accessor style element set and get are supported via method_missing
|
119
127
|
class VividMash < Mash
|
120
|
-
attr_reader :root
|
121
|
-
|
122
128
|
include CommonAPI
|
123
129
|
|
124
130
|
# Methods that mutate a VividMash. Each of them is overridden so that it
|
@@ -126,7 +132,6 @@ class Chef
|
|
126
132
|
# object.
|
127
133
|
MUTATOR_METHODS = [
|
128
134
|
:clear,
|
129
|
-
:delete,
|
130
135
|
:delete_if,
|
131
136
|
:keep_if,
|
132
137
|
:merge!,
|
@@ -140,23 +145,27 @@ class Chef
|
|
140
145
|
# For all of the mutating methods on Mash, override them so that they
|
141
146
|
# also invalidate the cached `merged_attributes` on the root Attribute
|
142
147
|
# object.
|
148
|
+
|
149
|
+
def delete(key, &block)
|
150
|
+
send_reset_cache(__path__, key)
|
151
|
+
super
|
152
|
+
end
|
153
|
+
|
143
154
|
MUTATOR_METHODS.each do |mutator|
|
144
155
|
define_method(mutator) do |*args, &block|
|
145
|
-
|
156
|
+
send_reset_cache
|
146
157
|
super(*args, &block)
|
147
158
|
end
|
148
159
|
end
|
149
160
|
|
150
|
-
def initialize(
|
151
|
-
@root = root
|
161
|
+
def initialize(data = {})
|
152
162
|
super(data)
|
153
163
|
end
|
154
164
|
|
155
165
|
def [](key)
|
156
|
-
root.top_level_breadcrumb ||= key
|
157
166
|
value = super
|
158
167
|
if !key?(key)
|
159
|
-
value = self.class.new(
|
168
|
+
value = self.class.new({}, __root__)
|
160
169
|
self[key] = value
|
161
170
|
else
|
162
171
|
value
|
@@ -164,9 +173,8 @@ class Chef
|
|
164
173
|
end
|
165
174
|
|
166
175
|
def []=(key, value)
|
167
|
-
root.top_level_breadcrumb ||= key
|
168
176
|
ret = super
|
169
|
-
|
177
|
+
send_reset_cache(__path__, key)
|
170
178
|
ret
|
171
179
|
end
|
172
180
|
|
@@ -205,9 +213,9 @@ class Chef
|
|
205
213
|
when AttrArray
|
206
214
|
value
|
207
215
|
when Hash
|
208
|
-
VividMash.new(
|
216
|
+
VividMash.new(value, __root__, __node__, __precedence__)
|
209
217
|
when Array
|
210
|
-
AttrArray.new(
|
218
|
+
AttrArray.new(value, __root__, __node__, __precedence__)
|
211
219
|
else
|
212
220
|
value
|
213
221
|
end
|
@@ -217,6 +225,7 @@ class Chef
|
|
217
225
|
Mash.new(self)
|
218
226
|
end
|
219
227
|
|
228
|
+
prepend Chef::Node::Mixin::StateTracking
|
220
229
|
end
|
221
230
|
end
|
222
231
|
end
|
data/lib/chef/node/common_api.rb
CHANGED
@@ -32,7 +32,6 @@ class Chef
|
|
32
32
|
# - autovivifying / autoreplacing writer
|
33
33
|
# - non-container-ey intermediate objects are replaced with hashes
|
34
34
|
def write(*args, &block)
|
35
|
-
root.top_level_breadcrumb = nil if respond_to?(:root)
|
36
35
|
value = block_given? ? yield : args.pop
|
37
36
|
last = args.pop
|
38
37
|
prev_memo = prev_key = nil
|
@@ -56,7 +55,6 @@ class Chef
|
|
56
55
|
# something that is not a container ("schema violation" issues).
|
57
56
|
#
|
58
57
|
def write!(*args, &block)
|
59
|
-
root.top_level_breadcrumb = nil if respond_to?(:root)
|
60
58
|
value = block_given? ? yield : args.pop
|
61
59
|
last = args.pop
|
62
60
|
obj = args.inject(self) do |memo, key|
|
@@ -71,7 +69,6 @@ class Chef
|
|
71
69
|
|
72
70
|
# return true or false based on if the attribute exists
|
73
71
|
def exist?(*path)
|
74
|
-
root.top_level_breadcrumb = nil if respond_to?(:root)
|
75
72
|
path.inject(self) do |memo, key|
|
76
73
|
return false unless valid_container?(memo, key)
|
77
74
|
if memo.is_a?(Hash)
|
@@ -103,7 +100,6 @@ class Chef
|
|
103
100
|
# non-autovivifying reader that throws an exception if the attribute does not exist
|
104
101
|
def read!(*path)
|
105
102
|
raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
|
106
|
-
root.top_level_breadcrumb = nil if respond_to?(:root)
|
107
103
|
path.inject(self) do |memo, key|
|
108
104
|
memo[key]
|
109
105
|
end
|
@@ -112,10 +108,8 @@ class Chef
|
|
112
108
|
# FIXME:(?) does anyone really like the autovivifying reader that we have and wants the same behavior? readers that write? ugh...
|
113
109
|
|
114
110
|
def unlink(*path, last)
|
115
|
-
root.top_level_breadcrumb = nil if respond_to?(:root)
|
116
111
|
hash = path.empty? ? self : read(*path)
|
117
112
|
return nil unless hash.is_a?(Hash) || hash.is_a?(Array)
|
118
|
-
root.top_level_breadcrumb ||= last
|
119
113
|
hash.delete(last)
|
120
114
|
end
|
121
115
|
|
@@ -16,6 +16,9 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
require "chef/node/common_api"
|
19
|
+
require "chef/node/mixin/state_tracking"
|
20
|
+
require "chef/node/mixin/immutablize_array"
|
21
|
+
require "chef/node/mixin/immutablize_hash"
|
19
22
|
|
20
23
|
class Chef
|
21
24
|
class Node
|
@@ -24,9 +27,9 @@ class Chef
|
|
24
27
|
def immutablize(value)
|
25
28
|
case value
|
26
29
|
when Hash
|
27
|
-
ImmutableMash.new(value)
|
30
|
+
ImmutableMash.new(value, __root__, __node__, __precedence__)
|
28
31
|
when Array
|
29
|
-
ImmutableArray.new(value)
|
32
|
+
ImmutableArray.new(value, __root__, __node__, __precedence__)
|
30
33
|
else
|
31
34
|
value
|
32
35
|
end
|
@@ -49,55 +52,12 @@ class Chef
|
|
49
52
|
alias :internal_push :<<
|
50
53
|
private :internal_push
|
51
54
|
|
52
|
-
|
53
|
-
# raise an error, making this instances of this class more or less
|
54
|
-
# immutable.
|
55
|
-
DISALLOWED_MUTATOR_METHODS = [
|
56
|
-
:<<,
|
57
|
-
:[]=,
|
58
|
-
:clear,
|
59
|
-
:collect!,
|
60
|
-
:compact!,
|
61
|
-
:default=,
|
62
|
-
:default_proc=,
|
63
|
-
:delete,
|
64
|
-
:delete_at,
|
65
|
-
:delete_if,
|
66
|
-
:fill,
|
67
|
-
:flatten!,
|
68
|
-
:insert,
|
69
|
-
:keep_if,
|
70
|
-
:map!,
|
71
|
-
:merge!,
|
72
|
-
:pop,
|
73
|
-
:push,
|
74
|
-
:update,
|
75
|
-
:reject!,
|
76
|
-
:reverse!,
|
77
|
-
:replace,
|
78
|
-
:select!,
|
79
|
-
:shift,
|
80
|
-
:slice!,
|
81
|
-
:sort!,
|
82
|
-
:sort_by!,
|
83
|
-
:uniq!,
|
84
|
-
:unshift,
|
85
|
-
]
|
86
|
-
|
87
|
-
def initialize(array_data)
|
55
|
+
def initialize(array_data = [])
|
88
56
|
array_data.each do |value|
|
89
57
|
internal_push(immutablize(value))
|
90
58
|
end
|
91
59
|
end
|
92
60
|
|
93
|
-
# Redefine all of the methods that mutate a Hash to raise an error when called.
|
94
|
-
# This is the magic that makes this object "Immutable"
|
95
|
-
DISALLOWED_MUTATOR_METHODS.each do |mutator_method_name|
|
96
|
-
define_method(mutator_method_name) do |*args, &block|
|
97
|
-
raise Exceptions::ImmutableAttributeModification
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
61
|
# For elements like Fixnums, true, nil...
|
102
62
|
def safe_dup(e)
|
103
63
|
e.dup
|
@@ -125,6 +85,13 @@ class Chef
|
|
125
85
|
a
|
126
86
|
end
|
127
87
|
|
88
|
+
# for consistency's sake -- integers 'converted' to integers
|
89
|
+
def convert_key(key)
|
90
|
+
key
|
91
|
+
end
|
92
|
+
|
93
|
+
prepend Chef::Node::Mixin::StateTracking
|
94
|
+
prepend Chef::Node::Mixin::ImmutablizeArray
|
128
95
|
end
|
129
96
|
|
130
97
|
# == ImmutableMash
|
@@ -140,36 +107,13 @@ class Chef
|
|
140
107
|
# it is stale.
|
141
108
|
# * Values can be accessed in attr_reader-like fashion via method_missing.
|
142
109
|
class ImmutableMash < Mash
|
143
|
-
|
144
110
|
include Immutablize
|
145
111
|
include CommonAPI
|
146
112
|
|
147
113
|
alias :internal_set :[]=
|
148
114
|
private :internal_set
|
149
115
|
|
150
|
-
|
151
|
-
:[]=,
|
152
|
-
:clear,
|
153
|
-
:collect!,
|
154
|
-
:default=,
|
155
|
-
:default_proc=,
|
156
|
-
:delete,
|
157
|
-
:delete_if,
|
158
|
-
:keep_if,
|
159
|
-
:map!,
|
160
|
-
:merge!,
|
161
|
-
:update,
|
162
|
-
:reject!,
|
163
|
-
:replace,
|
164
|
-
:select!,
|
165
|
-
:shift,
|
166
|
-
:write,
|
167
|
-
:write!,
|
168
|
-
:unlink,
|
169
|
-
:unlink!,
|
170
|
-
]
|
171
|
-
|
172
|
-
def initialize(mash_data)
|
116
|
+
def initialize(mash_data = {})
|
173
117
|
mash_data.each do |key, value|
|
174
118
|
internal_set(key, immutablize(value))
|
175
119
|
end
|
@@ -181,14 +125,6 @@ class Chef
|
|
181
125
|
|
182
126
|
alias :attribute? :has_key?
|
183
127
|
|
184
|
-
# Redefine all of the methods that mutate a Hash to raise an error when called.
|
185
|
-
# This is the magic that makes this object "Immutable"
|
186
|
-
DISALLOWED_MUTATOR_METHODS.each do |mutator_method_name|
|
187
|
-
define_method(mutator_method_name) do |*args, &block|
|
188
|
-
raise Exceptions::ImmutableAttributeModification
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
128
|
def method_missing(symbol, *args)
|
193
129
|
if symbol == :to_ary
|
194
130
|
super
|
@@ -238,7 +174,8 @@ class Chef
|
|
238
174
|
h
|
239
175
|
end
|
240
176
|
|
177
|
+
prepend Chef::Node::Mixin::StateTracking
|
178
|
+
prepend Chef::Node::Mixin::ImmutablizeHash
|
241
179
|
end
|
242
|
-
|
243
180
|
end
|
244
181
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright:: Copyright 2016, Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Node
|
20
|
+
module Mixin
|
21
|
+
module DeepMergeCache
|
22
|
+
# Cache of deep merged values by top-level key. This is a simple hash which has keys that are the
|
23
|
+
# top-level keys of the node object, and we save the computed deep-merge for that key here. There is
|
24
|
+
# no cache of subtrees.
|
25
|
+
attr_accessor :deep_merge_cache
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@merged_attributes = nil
|
29
|
+
@combined_override = nil
|
30
|
+
@combined_default = nil
|
31
|
+
@deep_merge_cache = {}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Invalidate a key in the deep_merge_cache. If called with nil, or no arg, this will invalidate
|
35
|
+
# the entire deep_merge cache. In the case of the user doing node.default['foo']['bar']['baz']=
|
36
|
+
# that eventually results in a call to reset_cache('foo') here. A node.default=hash_thing call
|
37
|
+
# must invalidate the entire cache and re-deep-merge the entire node object.
|
38
|
+
def reset_cache(path = nil)
|
39
|
+
if path.nil?
|
40
|
+
deep_merge_cache.clear
|
41
|
+
else
|
42
|
+
deep_merge_cache.delete(path.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
alias :reset :reset_cache
|
47
|
+
|
48
|
+
def [](key)
|
49
|
+
if deep_merge_cache.has_key?(key.to_s)
|
50
|
+
# return the cache of the deep merged values by top-level key
|
51
|
+
deep_merge_cache[key.to_s]
|
52
|
+
else
|
53
|
+
# save all the work of computing node[key]
|
54
|
+
deep_merge_cache[key.to_s] = merged_attributes(key)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright:: Copyright 2016, Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Chef
|
19
|
+
class Node
|
20
|
+
module Mixin
|
21
|
+
module ImmutablizeArray
|
22
|
+
# A list of methods that mutate Array. Each of these is overridden to
|
23
|
+
# raise an error, making this instances of this class more or less
|
24
|
+
# immutable.
|
25
|
+
DISALLOWED_MUTATOR_METHODS = [
|
26
|
+
:<<,
|
27
|
+
:[]=,
|
28
|
+
:clear,
|
29
|
+
:collect!,
|
30
|
+
:compact!,
|
31
|
+
:default=,
|
32
|
+
:default_proc=,
|
33
|
+
:delete,
|
34
|
+
:delete_at,
|
35
|
+
:delete_if,
|
36
|
+
:fill,
|
37
|
+
:flatten!,
|
38
|
+
:insert,
|
39
|
+
:keep_if,
|
40
|
+
:map!,
|
41
|
+
:merge!,
|
42
|
+
:pop,
|
43
|
+
:push,
|
44
|
+
:update,
|
45
|
+
:reject!,
|
46
|
+
:reverse!,
|
47
|
+
:replace,
|
48
|
+
:select!,
|
49
|
+
:shift,
|
50
|
+
:slice!,
|
51
|
+
:sort!,
|
52
|
+
:sort_by!,
|
53
|
+
:uniq!,
|
54
|
+
:unshift,
|
55
|
+
]
|
56
|
+
|
57
|
+
# Redefine all of the methods that mutate a Hash to raise an error when called.
|
58
|
+
# This is the magic that makes this object "Immutable"
|
59
|
+
DISALLOWED_MUTATOR_METHODS.each do |mutator_method_name|
|
60
|
+
define_method(mutator_method_name) do |*args, &block|
|
61
|
+
raise Exceptions::ImmutableAttributeModification
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|