right_support 2.8.37 → 2.8.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/right_support/data/hash_tools.rb +70 -3
- data/right_support.gemspec +4 -4
- data/spec/data/hash_tools_spec.rb +67 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0cb72f5d96896f6a249867296e5a6ee14021caa
|
4
|
+
data.tar.gz: 930f29d6b579d374ddadf6636c3687aeb12f394e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bc745e71199150c1c3097efe6ba4ec77549e6c5d34ae7fdd899710f5122adde38e77b01a56f4e826e8e49a297eed2534fc1be78cf72ffb924e79beb6335b064
|
7
|
+
data.tar.gz: e823929462c375b3bb12f51c91fd39780de10eec2194232d32c5ea649166709f523bc2cad31f4030d588a9f95eebd38ba84d969c6f4aa9a195f223d188fbac28
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.8.
|
1
|
+
2.8.38
|
@@ -138,6 +138,13 @@ module RightSupport::Data
|
|
138
138
|
# === Return
|
139
139
|
# @return [Hash] deep cloned hash
|
140
140
|
def self.deep_clone(original, &leaf_callback)
|
141
|
+
# note that .clone preserves .frozen? state so this legacy method will
|
142
|
+
# attempt to modify a still-frozen hash/array and raise an exception.
|
143
|
+
# see deep_clone2 which clones by creating a new instance of the object
|
144
|
+
# class and produce an unfrozen clone of the hash/array.
|
145
|
+
# as a side note, calling .dup does not preserve .frozen? state but is has
|
146
|
+
# its own side effects, which is why we have more specific logic like
|
147
|
+
# leaf_callback and .duplicable?
|
141
148
|
result = original.clone
|
142
149
|
result.each do |k, v|
|
143
150
|
if hashable?(v)
|
@@ -196,8 +203,36 @@ module RightSupport::Data
|
|
196
203
|
end
|
197
204
|
end
|
198
205
|
|
199
|
-
# Deeply
|
200
|
-
#
|
206
|
+
# Deeply freezes the given hash/array and all of their non-hierarchical
|
207
|
+
# elements in a hierarchichal data structure such that an attempt to modify
|
208
|
+
# any part of it will raise an exception.
|
209
|
+
#
|
210
|
+
# === Parameters
|
211
|
+
# @param [Object] any kind of object
|
212
|
+
#
|
213
|
+
# === Return
|
214
|
+
# @return [Object] deeply frozen object
|
215
|
+
def self.deep_freeze!(any)
|
216
|
+
if hashable?(any)
|
217
|
+
# clone to a new instance of hashable class with deep cloning.
|
218
|
+
any.each do |k, v|
|
219
|
+
# notes:
|
220
|
+
# a) either key or value of a hash could be a complex type.
|
221
|
+
# b) Hash freezes simple type keys upon insertion out of necessity to
|
222
|
+
# avoid spontaneous rehashing. Hash will not freeze complex types
|
223
|
+
# used as keys so we will (re)freeze all keys for safety.
|
224
|
+
deep_freeze!(k)
|
225
|
+
deep_freeze!(v)
|
226
|
+
end
|
227
|
+
elsif any.kind_of?(::Array)
|
228
|
+
# traverse arrays
|
229
|
+
any.each { |e| deep_freeze!(e) }
|
230
|
+
end
|
231
|
+
any.freeze
|
232
|
+
end
|
233
|
+
|
234
|
+
# Deeply mashes and duplicates (clones) a hashable using deep_clone2 and our
|
235
|
+
# own version of Mash.
|
201
236
|
#
|
202
237
|
# The advantage of Mash over Hash is, of course, to be able to use either
|
203
238
|
# a String or Symbol as a key for the same value.
|
@@ -221,7 +256,39 @@ module RightSupport::Data
|
|
221
256
|
deep_clone2(any, options, &leaf_callback)
|
222
257
|
end
|
223
258
|
|
224
|
-
# Performs a deep
|
259
|
+
# Performs a deep clone and merge of one hash into another, similar in
|
260
|
+
# behavior to Hash#merge
|
261
|
+
#
|
262
|
+
# === Parameters
|
263
|
+
# @param [Hash] target hash containing original data to be replaced in the
|
264
|
+
# resulting hash
|
265
|
+
# @param [Hash] source hash containing data to recursively assign or nil or
|
266
|
+
# empty
|
267
|
+
#
|
268
|
+
# === Return
|
269
|
+
# @return [Hash] to_hash result of merge
|
270
|
+
def self.deep_merge(target, source)
|
271
|
+
# merge or replace any values that appear in source.
|
272
|
+
result = target.class.new
|
273
|
+
(source || {}).each do |k, v|
|
274
|
+
if hashable?(target[k]) && hashable?(v)
|
275
|
+
result[k] = deep_merge(target[k], v)
|
276
|
+
else
|
277
|
+
result[k] = v
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# deep clone any target-only value.
|
282
|
+
target.each do |k, v|
|
283
|
+
unless result.has_key?(k)
|
284
|
+
result[k] = deep_clone2(v)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
result
|
288
|
+
end
|
289
|
+
|
290
|
+
# Performs a deep merge (but not a deep clone) of one hash into another,
|
291
|
+
# similar in behavior to Hash#merge!
|
225
292
|
#
|
226
293
|
# === Parameters
|
227
294
|
# @param [Hash] target hash to contain original and merged data
|
data/right_support.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: right_support 2.8.
|
5
|
+
# stub: right_support 2.8.38 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "right_support"
|
9
|
-
s.version = "2.8.
|
9
|
+
s.version = "2.8.38"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Tony Spataro", "Sergey Sergyenko", "Ryan Williamson", "Lee Kirchhoff", "Alexey Karpik", "Scott Messier"]
|
14
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-12-05"
|
15
15
|
s.description = "A toolkit of useful, reusable foundation code created by RightScale."
|
16
16
|
s.email = "support@rightscale.com"
|
17
17
|
s.extra_rdoc_files = [
|
@@ -148,7 +148,7 @@ Gem::Specification.new do |s|
|
|
148
148
|
]
|
149
149
|
s.homepage = "https://github.com/rightscale/right_support"
|
150
150
|
s.licenses = ["MIT"]
|
151
|
-
s.rubygems_version = "2.2.
|
151
|
+
s.rubygems_version = "2.2.2"
|
152
152
|
s.summary = "Reusable foundation code."
|
153
153
|
|
154
154
|
if s.respond_to? :specification_version then
|
@@ -257,6 +257,72 @@ describe RightSupport::Data::HashTools do
|
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
260
|
+
context '#deep_freeze!' do
|
261
|
+
it "should deep freeze hashes and arrays" do
|
262
|
+
original = {
|
263
|
+
'a' => ' s ',
|
264
|
+
'b' => {
|
265
|
+
'h' => ' s2 ',
|
266
|
+
'a' => [ 1, { :nested => ' s3 ' } ]
|
267
|
+
}
|
268
|
+
}
|
269
|
+
original.each do |k, v|
|
270
|
+
# note that Hash freezes keys upon insertion out of necessity to avoid
|
271
|
+
# spontaneous rehashing.
|
272
|
+
k.should be_frozen
|
273
|
+
v.should_not be_frozen
|
274
|
+
end
|
275
|
+
original['b']['a'][1][:nested].should_not be_frozen
|
276
|
+
subject.deep_freeze!(original)
|
277
|
+
original.each do |k, v|
|
278
|
+
k.should be_frozen
|
279
|
+
v.should be_frozen
|
280
|
+
end
|
281
|
+
original['b']['a'][1][:nested].should be_frozen
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context '#deep_merge' do
|
286
|
+
{
|
287
|
+
:identical => {
|
288
|
+
:left => { :one => 1 },
|
289
|
+
:right => { :one => 1 },
|
290
|
+
:expected => { :one => 1 } },
|
291
|
+
:disjoint => {
|
292
|
+
:left => { :one => 1 },
|
293
|
+
:right => { :two => 1 },
|
294
|
+
:expected => { :one => 1, :two => 1 } },
|
295
|
+
:value_diff => {
|
296
|
+
:left => { :one => 1 },
|
297
|
+
:right => { :one => 2 },
|
298
|
+
:expected => { :one => 2 } },
|
299
|
+
:recursive_disjoint => {
|
300
|
+
:left => { :one => { :a => 1, :b => 2 }, :two => 3 },
|
301
|
+
:right => { :one => { :a => 1 }, :two => 3 },
|
302
|
+
:expected => { :one => { :a => 1, :b => 2 }, :two => 3 } },
|
303
|
+
:recursive_value_diff => {
|
304
|
+
:left => { :one => { :a => 1, :b => 2 }, :two => 3 },
|
305
|
+
:right => { :one => { :a => 1, :b => 3 }, :two => 3 },
|
306
|
+
:expected => { :one => { :a => 1, :b => 3 }, :two => 3 } },
|
307
|
+
:recursive_disjoint_and_value_diff => {
|
308
|
+
:left => { :one => { :a => 1, :b => 2, :c => 3 }, :two => 3, :three => 4 },
|
309
|
+
:right => { :one => { :a => 1, :b => 3, :d => 4 }, :two => 5, :four => 6 },
|
310
|
+
:expected => { :one => { :a => 1, :b => 3, :c => 3 , :d => 4 }, :two => 5, :three => 4, :four => 6 } }
|
311
|
+
}.each do |kind, data|
|
312
|
+
it "should deep merge #{kind} hashes" do
|
313
|
+
left_same_as_expected = data[:left] == data[:expected]
|
314
|
+
actual = subject.deep_merge(data[:left], data[:right])
|
315
|
+
actual.should == data[:expected]
|
316
|
+
|
317
|
+
# original should be unmodified.
|
318
|
+
actual.object_id.should_not == data[:left].object_id
|
319
|
+
unless left_same_as_expected
|
320
|
+
data[:left].should_not == data[:expected]
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
260
326
|
context '#deep_merge!' do
|
261
327
|
{
|
262
328
|
:identical => {
|
@@ -287,6 +353,7 @@ describe RightSupport::Data::HashTools do
|
|
287
353
|
it "should deep merge #{kind} hashes" do
|
288
354
|
actual = subject.deep_merge!(data[:left], data[:right])
|
289
355
|
actual.should == data[:expected]
|
356
|
+
actual.object_id.should == data[:left].object_id # original returned modified
|
290
357
|
end
|
291
358
|
end
|
292
359
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.38
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2014-
|
16
|
+
date: 2014-12-05 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: rake
|
@@ -239,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
239
239
|
version: '0'
|
240
240
|
requirements: []
|
241
241
|
rubyforge_project:
|
242
|
-
rubygems_version: 2.2.
|
242
|
+
rubygems_version: 2.2.2
|
243
243
|
signing_key:
|
244
244
|
specification_version: 4
|
245
245
|
summary: Reusable foundation code.
|