Skip to content

Commit

Permalink
Added deep freezable module
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Naiman committed Mar 29, 2019
1 parent 53e37d2 commit c6998e4
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 5 deletions.
1 change: 1 addition & 0 deletions lib/hash_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'hash_ext/version'

require_relative 'hash_ext/deep_freezable'
require_relative 'hash_ext/normalized'
require_relative 'hash_ext/builder'
require_relative 'hash_ext/indifferent'
Expand Down
25 changes: 25 additions & 0 deletions lib/hash_ext/deep_freezable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Hash
module DeepFreezable

def deep_freeze
each_value { |v| deep_freeze_value v }
freeze
end

def deep_freeze_value(value)
if value.respond_to? :deep_freeze
value.deep_freeze
else
if value.is_a? Hash
value.each_value { |v| deep_freeze_value v }
elsif value.respond_to? :each
value.each { |v| deep_freeze_value v }
end
value.freeze
end
end

private :deep_freeze_value

end
end
2 changes: 2 additions & 0 deletions lib/hash_ext/nested.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class Hash
class Nested < Hash

include DeepFreezable

def [](key)
if key? key
super(key)
Expand Down
2 changes: 2 additions & 0 deletions lib/hash_ext/normalized.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class Hash
class Normalized < Hash

include DeepFreezable

def self.subclass(&block)
Class.new(self) do
define_method :initialize do |hash={}|
Expand Down
1 change: 1 addition & 0 deletions lib/hash_ext/sorted.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class Sorted

extend Forwardable
include Enumerable
include DeepFreezable

def_delegators :@hash, :[], :[]=, :value?, :fetch, :values_at,
:key?, :include?, :empty?,
Expand Down
17 changes: 17 additions & 0 deletions spec/accessible_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,21 @@
hash.a[0].must_equal 3
end

it 'Deep freeze' do
h = Hash::Accessible.new a: 1, b: [{x: 1}, {x: 2}], c: {x: 1, y: {z: 2}}
h.deep_freeze

h.must_be :frozen?
h.a.must_be :frozen?
h.b.must_be :frozen?
h.b[0].must_be :frozen?
h.b[0].x.must_be :frozen?
h.b[1].must_be :frozen?
h.b[1].x.must_be :frozen?
h.c.must_be :frozen?
h.c.x.must_be :frozen?
h.c.y.must_be :frozen?
h.c.y.z.must_be :frozen?
end

end
18 changes: 18 additions & 0 deletions spec/indifferent_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,22 @@
Marshal.load(Marshal.dump(hash)).must_equal hash
end

it 'Deep freeze' do
h = Hash::Indifferent.new a: 1, b: [{x: 1}, {x: 2}], c: {x: 1, y: {z: 2}}
h.deep_freeze

h.must_be :frozen?

h[:a].must_be :frozen?
h[:b].must_be :frozen?
h[:b][0].must_be :frozen?
h['b'][0][:x].must_be :frozen?
h['b'][1].must_be :frozen?
h[:b][1]['x'].must_be :frozen?
h[:c].must_be :frozen?
h[:c][:x].must_be :frozen?
h['c'][:y].must_be :frozen?
h['c']['y'][:z].must_be :frozen?
end

end
11 changes: 11 additions & 0 deletions spec/nested_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@
hash.must_equal level_1: {level_2: {level_3: 'test'}}
end

it 'Deep freeze' do
hash = Hash::Nested.new
hash[:level_1][:level_2][:level_3] = 'test'

hash.deep_freeze

hash[:level_1].must_be :frozen?
hash[:level_1][:level_2].must_be :frozen?
hash[:level_1][:level_2][:level_3].must_be :frozen?
end

end
27 changes: 22 additions & 5 deletions spec/normalized_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Insensitive = Hash::Normalized.subclass { |key| key.to_s.downcase }

it 'case insensitive' do
it 'Case insensitive' do
hash = Insensitive.new
hash["A"] = 1
hash[:B] = 2
Expand All @@ -16,7 +16,7 @@
hash[:b].must_equal 2
end

it 'merge' do
it 'Merge' do
h1 = Insensitive.new a: 100, b: 200
h2 = Insensitive.new B: 254, c: 300
m = h1.merge h2
Expand All @@ -26,7 +26,7 @@
m[:c].must_equal 300
end

it 'merge with block' do
it 'Merge with block' do
h1 = Insensitive.new a: 100, b: 200
h2 = Insensitive.new B: 254, c: 300
m = h1.merge(h2) { |key, oldval, newval | newval - oldval }
Expand All @@ -36,7 +36,7 @@
m[:c].must_equal 300
end

it 'update' do
it 'Update' do
h1 = Insensitive.new a: 100, b:200
h2 = Insensitive.new B: 254, c:300
h1.update(h2)
Expand All @@ -46,7 +46,7 @@
h1[:c].must_equal 300
end

it 'update with block' do
it 'Update with block' do
h1 = Insensitive.new a: 100, b:200
h2 = Insensitive.new B: 254, c:300
h1.update(h2) { |key, v1, v2| v1 }
Expand All @@ -56,4 +56,21 @@
h1[:c].must_equal 300
end

it 'Deep freeze' do
h = Insensitive.new a: 1, b: [{x: 1}, {x: 2}], c: {x: 1, y: {z: 2}}
h.deep_freeze

h.must_be :frozen?
h[:A].must_be :frozen?
h[:b].must_be :frozen?
h[:B][0].must_be :frozen?
h['b'][0][:x].must_be :frozen?
h['B'][1].must_be :frozen?
h[:b][1]['X'].must_be :frozen?
h[:c].must_be :frozen?
h[:C][:x].must_be :frozen?
h['c'][:Y].must_be :frozen?
h['C']['y'][:Z].must_be :frozen?
end

end
18 changes: 18 additions & 0 deletions spec/sorted_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,22 @@ def fill(hash)
h.values.must_equal [2, 4, 1, 3]
end

it 'Deep freeze' do
values = {a: 1, b: [{x: 1}, {x: 2}], c: {x: 1, y: {z: 2}}}
h = Hash::Sorted.asc(values) { |k,v| k }
h.deep_freeze

h.must_be :frozen?
h[:a].must_be :frozen?
h[:b].must_be :frozen?
h[:b][0].must_be :frozen?
h[:b][0][:x].must_be :frozen?
h[:b][1].must_be :frozen?
h[:b][1][:x].must_be :frozen?
h[:c].must_be :frozen?
h[:c][:x].must_be :frozen?
h[:c][:y].must_be :frozen?
h[:c][:y][:z].must_be :frozen?
end

end

0 comments on commit c6998e4

Please sign in to comment.