ice_nine 0.9.0 → 0.10.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 +9 -9
- data/.travis.yml +9 -17
- data/Gemfile.devtools +4 -4
- data/benchmarks/speed.rb +32 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +1 -1
- data/lib/ice_nine.rb +4 -3
- data/lib/ice_nine/freezer/array.rb +6 -2
- data/lib/ice_nine/freezer/hash.rb +5 -4
- data/lib/ice_nine/freezer/no_freeze.rb +1 -1
- data/lib/ice_nine/freezer/object.rb +9 -4
- data/lib/ice_nine/freezer/range.rb +4 -3
- data/lib/ice_nine/support/recursion_guard.rb +18 -26
- data/lib/ice_nine/version.rb +1 -1
- data/spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb +19 -0
- data/spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb +15 -3
- data/spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb +36 -26
- data/spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb +20 -6
- data/spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb +11 -7
- data/spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb +21 -7
- data/spec/unit/ice_nine/freezer/range/class_methods/deep_freeze_spec.rb +45 -2
- data/spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb +4 -4
- data/spec/unit/object/deep_freeze_spec.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWEyOTlkYzI1MTM2YTg3YjdmMTg0MzU1MzA5NjQwOTBkNzViOTg3NQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
7
|
-
|
6
|
+
ZDM3ZmJkYzE4MjFjZTdiOGMyODJhNTg3NzJiNmNmNjJlYjE1MTM4OQ==
|
7
|
+
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NGFlY2QxNDNmOWE2MDBjYmUyMzE5ZTU2NzE4ZmQxNDQ1OTMzNTFkZmFlNDJj
|
10
|
+
YjlkODVhNWI3MmFiYzBmZTA0ZTViZjg0YmJjZDNhMmZjZDk4NTA1MzQzYzdm
|
11
|
+
YWI3N2QzOTZkMGQwMDU5ODIxMmFlOWNjMzJmMzlkOGY3YzRlMzA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzQ5ZWY3NjQ4ZTJjNjYzZjMxZGI4Nzk3MGI1OGEzZmQ2NjQ5ZDExOTU0NDM1
|
14
|
+
OTRlNWY2ZDFiMTEzNDhkNTcwZmE4NTc4NTE2NWU1NGJjM2M2YTg4MDdjM2Q4
|
15
|
+
N2JiMjlmYzM2Mzk3YjQ3YTJkNzBkODdjM2JlNzMwNzNmNDc5ODU=
|
data/.travis.yml
CHANGED
@@ -1,23 +1,11 @@
|
|
1
1
|
language: ruby
|
2
|
-
before_install: gem install bundler
|
3
2
|
bundler_args: --without yard guard benchmarks
|
4
3
|
script: "bundle exec rake ci"
|
5
4
|
rvm:
|
6
5
|
- 1.9.3
|
7
6
|
- 2.0.0
|
8
7
|
- ruby-head
|
9
|
-
|
10
|
-
notifications:
|
11
|
-
irc:
|
12
|
-
channels:
|
13
|
-
- irc.freenode.org#rom-rb
|
14
|
-
on_success: never
|
15
|
-
on_failure: change
|
16
|
-
email:
|
17
|
-
recipients:
|
18
|
-
- dan.kubb@gmail.com
|
19
|
-
on_success: never
|
20
|
-
on_failure: change
|
8
|
+
- rbx-19mode
|
21
9
|
matrix:
|
22
10
|
include:
|
23
11
|
- rvm: jruby-19mode
|
@@ -25,7 +13,11 @@ matrix:
|
|
25
13
|
- rvm: jruby-head
|
26
14
|
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
27
15
|
allow_failures:
|
28
|
-
|
29
|
-
- rvm:
|
30
|
-
|
31
|
-
|
16
|
+
- rvm: ruby-head # travis broken
|
17
|
+
- rvm: rbx-19mode # mutant fails
|
18
|
+
notifications:
|
19
|
+
irc:
|
20
|
+
channels:
|
21
|
+
- irc.freenode.org#rom-rb
|
22
|
+
on_success: never
|
23
|
+
on_failure: change
|
data/Gemfile.devtools
CHANGED
@@ -7,7 +7,7 @@ group :development do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
group :yard do
|
10
|
-
gem 'kramdown', '~> 1.
|
10
|
+
gem 'kramdown', '~> 1.2.0'
|
11
11
|
end
|
12
12
|
|
13
13
|
group :guard do
|
@@ -15,7 +15,7 @@ group :guard do
|
|
15
15
|
gem 'guard-bundler', '~> 1.0.0'
|
16
16
|
gem 'guard-rspec', '~> 3.0.2'
|
17
17
|
gem 'guard-rubocop', '~> 0.2.0'
|
18
|
-
|
18
|
+
gem 'guard-mutant', '~> 0.0.1'
|
19
19
|
|
20
20
|
# file system change event handling
|
21
21
|
gem 'listen', '~> 1.3.0'
|
@@ -34,12 +34,12 @@ group :metrics do
|
|
34
34
|
gem 'flay', '~> 2.4.0'
|
35
35
|
gem 'flog', '~> 4.1.1'
|
36
36
|
gem 'reek', '~> 1.3.2'
|
37
|
-
gem 'rubocop', '~> 0.
|
37
|
+
gem 'rubocop', '~> 0.13.0'
|
38
38
|
gem 'simplecov', '~> 0.7.1'
|
39
39
|
gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
|
40
40
|
|
41
41
|
platforms :ruby_19, :ruby_20 do
|
42
|
-
|
42
|
+
gem 'mutant', git: 'https://github.com/mbj/mutant.git'
|
43
43
|
gem 'yard-spellcheck', '~> 0.1.5'
|
44
44
|
end
|
45
45
|
end
|
data/benchmarks/speed.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
# benchmark speed of deep freeze
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
8
|
+
|
9
|
+
require 'rbench'
|
10
|
+
require 'ice_nine'
|
11
|
+
|
12
|
+
# @return [Hash]
|
13
|
+
def self.nested(depth, width, array_length)
|
14
|
+
hash = {}
|
15
|
+
|
16
|
+
1.upto(width) do |n|
|
17
|
+
hash[n.to_s] = n.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
unless depth == 1
|
21
|
+
hash[(width - 1).to_s] = array_length.times.map { nested(depth - 1, width, array_length) }
|
22
|
+
hash[width.to_s] = nested(depth - 1, width, array_length)
|
23
|
+
end
|
24
|
+
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
|
28
|
+
hash = nested(3, 5, 100)
|
29
|
+
|
30
|
+
RBench.run do
|
31
|
+
report("deep_freeze") { IceNine.deep_freeze(hash) }
|
32
|
+
end
|
data/config/flay.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
3
|
-
total_score:
|
2
|
+
threshold: 5
|
3
|
+
total_score: 29.0
|
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 9.1
|
data/config/reek.yml
CHANGED
data/lib/ice_nine.rb
CHANGED
@@ -32,14 +32,15 @@ module IceNine
|
|
32
32
|
# object = IceNine.deep_freeze(object)
|
33
33
|
#
|
34
34
|
# @param [Object] object
|
35
|
+
# @param [RecursionGuard] recursion_guard
|
35
36
|
#
|
36
37
|
# @return [Object]
|
37
38
|
#
|
38
39
|
# @api public
|
39
|
-
def self.deep_freeze(object)
|
40
|
+
def self.deep_freeze(object, recursion_guard = RecursionGuard.new)
|
40
41
|
return object if object.frozen?
|
41
|
-
|
42
|
-
Freezer[object.class].deep_freeze(object)
|
42
|
+
recursion_guard.guard(object.__id__) do
|
43
|
+
Freezer[object.class].deep_freeze(object, recursion_guard)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
@@ -13,12 +13,16 @@ module IceNine
|
|
13
13
|
# array.select(&:frozen?) # => ['a', 'b', 'c']
|
14
14
|
#
|
15
15
|
# @param [Array] array
|
16
|
+
# @param [RecursionGuard] recursion_guard
|
16
17
|
#
|
17
18
|
# @return [Array]
|
18
19
|
#
|
19
20
|
# @api public
|
20
|
-
def self.deep_freeze(array)
|
21
|
-
|
21
|
+
def self.deep_freeze(array, recursion_guard = RecursionGuard.new)
|
22
|
+
array.each do |entry|
|
23
|
+
IceNine.deep_freeze(entry, recursion_guard)
|
24
|
+
end
|
25
|
+
super
|
22
26
|
end
|
23
27
|
|
24
28
|
end # class Array
|
@@ -14,15 +14,16 @@ module IceNine
|
|
14
14
|
# hash.values.select(&:frozen?) # => ['1', '2']
|
15
15
|
#
|
16
16
|
# @param [Hash] hash
|
17
|
+
# @param [RecursionGuard] recursion_guard
|
17
18
|
#
|
18
19
|
# @return [Hash]
|
19
20
|
#
|
20
21
|
# @api public
|
21
|
-
def self.deep_freeze(hash)
|
22
|
-
IceNine.deep_freeze(hash.default_proc || hash.default)
|
22
|
+
def self.deep_freeze(hash, recursion_guard = RecursionGuard.new)
|
23
|
+
IceNine.deep_freeze(hash.default_proc || hash.default, recursion_guard)
|
23
24
|
hash.each do |key, value|
|
24
|
-
IceNine.deep_freeze(key)
|
25
|
-
IceNine.deep_freeze(value)
|
25
|
+
IceNine.deep_freeze(key, recursion_guard)
|
26
|
+
IceNine.deep_freeze(value, recursion_guard)
|
26
27
|
end
|
27
28
|
super
|
28
29
|
end
|
@@ -12,25 +12,30 @@ module IceNine
|
|
12
12
|
# object = IceNine.deep_freeze(Object.new)
|
13
13
|
#
|
14
14
|
# @param [Object] object
|
15
|
+
# @param [RecursionGuard] recursion_guard
|
15
16
|
#
|
16
17
|
# @return [Object]
|
17
18
|
#
|
18
19
|
# @api public
|
19
|
-
def self.deep_freeze(object)
|
20
|
-
freeze_instance_variables(object)
|
20
|
+
def self.deep_freeze(object, recursion_guard = RecursionGuard.new)
|
21
|
+
freeze_instance_variables(object, recursion_guard)
|
21
22
|
object.freeze
|
22
23
|
end
|
23
24
|
|
24
25
|
# Handle freezing the object's instance variables
|
25
26
|
#
|
26
27
|
# @param [Object] object
|
28
|
+
# @param [RecursionGuard] recursion_guard
|
27
29
|
#
|
28
30
|
# @return [undefined]
|
29
31
|
#
|
30
32
|
# @api private
|
31
|
-
def self.freeze_instance_variables(object)
|
33
|
+
def self.freeze_instance_variables(object, recursion_guard)
|
32
34
|
object.instance_variables.each do |ivar_name|
|
33
|
-
IceNine.deep_freeze(
|
35
|
+
IceNine.deep_freeze(
|
36
|
+
object.instance_variable_get(ivar_name),
|
37
|
+
recursion_guard
|
38
|
+
)
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
@@ -14,13 +14,14 @@ module IceNine
|
|
14
14
|
# range.end.frozen? # => true
|
15
15
|
#
|
16
16
|
# @param [Range] range
|
17
|
+
# @param [RecursionGuard] recursion_guard
|
17
18
|
#
|
18
19
|
# @return [Range]
|
19
20
|
#
|
20
21
|
# @api public
|
21
|
-
def self.deep_freeze(range)
|
22
|
-
IceNine.deep_freeze(range.begin)
|
23
|
-
IceNine.deep_freeze(range.end)
|
22
|
+
def self.deep_freeze(range, recursion_guard = RecursionGuard.new)
|
23
|
+
IceNine.deep_freeze(range.begin, recursion_guard)
|
24
|
+
IceNine.deep_freeze(range.end, recursion_guard)
|
24
25
|
super
|
25
26
|
end
|
26
27
|
|
@@ -3,43 +3,35 @@
|
|
3
3
|
module IceNine
|
4
4
|
|
5
5
|
# Protect against infinite recursion
|
6
|
-
|
6
|
+
class RecursionGuard
|
7
|
+
|
8
|
+
# Initialize a recursion guard
|
9
|
+
#
|
10
|
+
# @return [undefined]
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
def initialize
|
14
|
+
@object_ids = {}
|
15
|
+
end
|
7
16
|
|
8
17
|
# Guard against recursively calling a block with the same object
|
9
18
|
#
|
10
19
|
# @example
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
20
|
+
# recursion_guard = IceNine::RecursionGuard.new
|
21
|
+
# recursion_guard.guard(object_id) do
|
22
|
+
# logic_which_may_be_recursively_called_with_object_id(recursion_guard)
|
23
|
+
# end
|
14
24
|
#
|
15
25
|
# @param [Integer] caller_object_id
|
16
26
|
#
|
17
27
|
# @return [Object]
|
18
28
|
#
|
19
29
|
# @api public
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
objects << caller_object_id
|
25
|
-
yield
|
26
|
-
ensure
|
27
|
-
objects.delete(caller_object_id)
|
28
|
-
end
|
30
|
+
def guard(caller_object_id)
|
31
|
+
return if @object_ids.key?(caller_object_id)
|
32
|
+
@object_ids[caller_object_id] = nil
|
33
|
+
yield
|
29
34
|
end
|
30
35
|
|
31
|
-
# The current objects guarded at a specific location in the source
|
32
|
-
#
|
33
|
-
# @param [String] location
|
34
|
-
#
|
35
|
-
# @return [Set<Integer>]
|
36
|
-
#
|
37
|
-
# @api private
|
38
|
-
def self.guarded_objects(location)
|
39
|
-
Thread.current[location] ||= Set.new
|
40
|
-
end
|
41
|
-
|
42
|
-
private_class_method :guarded_objects
|
43
|
-
|
44
36
|
end # RecursionGuard
|
45
37
|
end # module IceNine
|
data/lib/ice_nine/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'ice_nine'
|
5
|
+
require 'ice_nine/core_ext/object'
|
6
|
+
|
7
|
+
describe IceNine::CoreExt::Object, '#deep_freeze' do
|
8
|
+
subject { object.deep_freeze }
|
9
|
+
|
10
|
+
let(:object) { Object.new.extend(IceNine::CoreExt::Object) }
|
11
|
+
|
12
|
+
it 'returns the object' do
|
13
|
+
should be(object)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'freezes the object' do
|
17
|
+
expect { subject }.to change(object, :frozen?).from(false).to(true)
|
18
|
+
end
|
19
|
+
end
|
@@ -8,9 +8,7 @@ describe IceNine::Freezer::Array, '.deep_freeze' do
|
|
8
8
|
|
9
9
|
let(:object) { described_class }
|
10
10
|
|
11
|
-
|
12
|
-
let(:value) { %w[a] }
|
13
|
-
|
11
|
+
shared_examples 'IceNine::Freezer::Array.deep_freeze' do
|
14
12
|
it 'returns the object' do
|
15
13
|
should be(value)
|
16
14
|
end
|
@@ -23,4 +21,18 @@ describe IceNine::Freezer::Array, '.deep_freeze' do
|
|
23
21
|
expect(subject.select(&:frozen?)).to eql(subject)
|
24
22
|
end
|
25
23
|
end
|
24
|
+
|
25
|
+
context 'with an Array object' do
|
26
|
+
let(:value) { %w[a] }
|
27
|
+
|
28
|
+
context 'without a circular reference' do
|
29
|
+
it_behaves_like 'IceNine::Freezer::Array.deep_freeze'
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with a circular reference' do
|
33
|
+
before { value << value }
|
34
|
+
|
35
|
+
it_behaves_like 'IceNine::Freezer::Array.deep_freeze'
|
36
|
+
end
|
37
|
+
end
|
26
38
|
end
|
@@ -8,11 +8,7 @@ describe IceNine::Freezer::Hash, '.deep_freeze' do
|
|
8
8
|
|
9
9
|
let(:object) { described_class }
|
10
10
|
|
11
|
-
|
12
|
-
let(:value) do
|
13
|
-
Hash.new {}.update(Object.new => Object.new)
|
14
|
-
end
|
15
|
-
|
11
|
+
shared_examples 'IceNine::Freezer::Hash.deep_freeze' do
|
16
12
|
it 'returns the object' do
|
17
13
|
should be(value)
|
18
14
|
end
|
@@ -21,10 +17,6 @@ describe IceNine::Freezer::Hash, '.deep_freeze' do
|
|
21
17
|
expect { subject }.to change(value, :frozen?).from(false).to(true)
|
22
18
|
end
|
23
19
|
|
24
|
-
it 'freezes the default proc' do
|
25
|
-
expect(subject.default_proc).to be_frozen
|
26
|
-
end
|
27
|
-
|
28
20
|
it 'freezes each key in the Hash' do
|
29
21
|
expect(subject.keys.select(&:frozen?)).to eql(subject.keys)
|
30
22
|
end
|
@@ -44,39 +36,57 @@ describe IceNine::Freezer::Hash, '.deep_freeze' do
|
|
44
36
|
end
|
45
37
|
end
|
46
38
|
|
47
|
-
context 'with a Hash object having a default
|
39
|
+
context 'with a Hash object having a default proc' do
|
48
40
|
let(:value) do
|
49
|
-
Hash.new
|
41
|
+
Hash.new {}.update(Object.new => Object.new)
|
50
42
|
end
|
51
43
|
|
52
|
-
|
53
|
-
|
44
|
+
it_behaves_like 'IceNine::Freezer::Hash.deep_freeze'
|
45
|
+
|
46
|
+
it 'freezes the default proc' do
|
47
|
+
expect(subject.default_proc).to be_frozen
|
54
48
|
end
|
49
|
+
end
|
55
50
|
|
56
|
-
|
57
|
-
|
51
|
+
context 'with a Hash object having a default value' do
|
52
|
+
let(:value) do
|
53
|
+
Hash.new('').update(Object.new => Object.new)
|
58
54
|
end
|
59
55
|
|
56
|
+
it_behaves_like 'IceNine::Freezer::Hash.deep_freeze'
|
57
|
+
|
60
58
|
it 'freezes the default value' do
|
61
59
|
expect(subject.default).to be_frozen
|
62
60
|
end
|
63
61
|
|
64
|
-
|
65
|
-
|
62
|
+
context 'that is a circular reference' do
|
63
|
+
before { value.default = value }
|
64
|
+
|
65
|
+
it_behaves_like 'IceNine::Freezer::Hash.deep_freeze'
|
66
|
+
|
67
|
+
it 'freezes the default value' do
|
68
|
+
expect(subject.default).to be_frozen
|
69
|
+
end
|
66
70
|
end
|
71
|
+
end
|
67
72
|
|
68
|
-
|
69
|
-
|
73
|
+
context 'with a Hash object containing itself as a key' do
|
74
|
+
let(:value) do
|
75
|
+
value = {}
|
76
|
+
value[value] = '1'
|
77
|
+
value
|
70
78
|
end
|
71
79
|
|
72
|
-
|
73
|
-
|
74
|
-
expect(subject.instance_variable_get(:@state)).to_not be_frozen
|
75
|
-
end
|
80
|
+
it_behaves_like 'IceNine::Freezer::Hash.deep_freeze'
|
81
|
+
end
|
76
82
|
|
77
|
-
|
78
|
-
|
79
|
-
|
83
|
+
context 'with a Hash object containing itself as a value' do
|
84
|
+
let(:value) do
|
85
|
+
value = {}
|
86
|
+
value['a'] = value
|
87
|
+
value
|
80
88
|
end
|
89
|
+
|
90
|
+
it_behaves_like 'IceNine::Freezer::Hash.deep_freeze'
|
81
91
|
end
|
82
92
|
end
|
@@ -4,16 +4,30 @@ require 'spec_helper'
|
|
4
4
|
require 'ice_nine/freezer/no_freeze'
|
5
5
|
|
6
6
|
describe IceNine::Freezer::NoFreeze, '.deep_freeze' do
|
7
|
-
subject { object.deep_freeze(value) }
|
8
|
-
|
9
7
|
let(:object) { described_class }
|
10
8
|
let(:value) { double('value') }
|
11
9
|
|
12
|
-
|
13
|
-
|
10
|
+
shared_examples 'IceNine::Freezer::NoFreeze.deep_freeze' do
|
11
|
+
it 'returns the object' do
|
12
|
+
should be(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does not freeze the object' do
|
16
|
+
expect { subject }.to_not change(value, :frozen?).from(false)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
|
-
|
17
|
-
|
20
|
+
context 'with a recursion guard' do
|
21
|
+
subject { object.deep_freeze(value, recursion_guard) }
|
22
|
+
|
23
|
+
let(:recursion_guard) { double('recursion_guard') }
|
24
|
+
|
25
|
+
it_behaves_like 'IceNine::Freezer::NoFreeze.deep_freeze'
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'without a recursion guard' do
|
29
|
+
subject { object.deep_freeze(value) }
|
30
|
+
|
31
|
+
it_behaves_like 'IceNine::Freezer::NoFreeze.deep_freeze'
|
18
32
|
end
|
19
33
|
end
|
@@ -10,17 +10,21 @@ describe IceNine::Freezer::Numeric, '.deep_freeze' do
|
|
10
10
|
|
11
11
|
let(:object) { described_class }
|
12
12
|
|
13
|
+
shared_examples 'IceNine::Freezer::Numeric.deep_freeze' do
|
14
|
+
it 'returns the object' do
|
15
|
+
should be(value)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not freeze the object' do
|
19
|
+
expect { subject }.to_not change(value, :frozen?).from(false)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
13
23
|
[0.0, 0, 0x7fffffffffffffff].each do |value|
|
14
24
|
context "with a #{value.class} object" do
|
15
25
|
let(:value) { value }
|
16
26
|
|
17
|
-
|
18
|
-
should be(value)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'does not freeze the object' do
|
22
|
-
expect { subject }.to_not change(value, :frozen?).from(false)
|
23
|
-
end
|
27
|
+
it_behaves_like 'IceNine::Freezer::Numeric.deep_freeze'
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
@@ -8,13 +8,7 @@ describe IceNine::Freezer::Object, '.deep_freeze' do
|
|
8
8
|
|
9
9
|
let(:object) { described_class }
|
10
10
|
|
11
|
-
|
12
|
-
let(:value) { Object.new }
|
13
|
-
|
14
|
-
before do
|
15
|
-
value.instance_eval { @a = '1' }
|
16
|
-
end
|
17
|
-
|
11
|
+
shared_examples 'IceNine::Freezer::Object.deep_freeze' do
|
18
12
|
it 'returns the object' do
|
19
13
|
should be(value)
|
20
14
|
end
|
@@ -27,4 +21,24 @@ describe IceNine::Freezer::Object, '.deep_freeze' do
|
|
27
21
|
expect(subject.instance_variable_get(:@a)).to be_frozen
|
28
22
|
end
|
29
23
|
end
|
24
|
+
|
25
|
+
context 'with an Object' do
|
26
|
+
let(:value) { Object.new }
|
27
|
+
|
28
|
+
before do
|
29
|
+
value.instance_eval { @a = '1' }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'without a circular reference' do
|
33
|
+
it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with a circular reference' do
|
37
|
+
before do
|
38
|
+
value.instance_eval { @b = self }
|
39
|
+
end
|
40
|
+
|
41
|
+
it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
|
42
|
+
end
|
43
|
+
end
|
30
44
|
end
|
@@ -8,9 +8,32 @@ describe IceNine::Freezer::Range, '.deep_freeze' do
|
|
8
8
|
|
9
9
|
let(:object) { described_class }
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
let(:element_class) do
|
12
|
+
Class.new do
|
13
|
+
attr_reader :number, :range
|
14
|
+
protected :number, :range
|
15
|
+
|
16
|
+
def initialize(number, range = nil)
|
17
|
+
@number = number
|
18
|
+
@range = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def succ
|
22
|
+
self.class.new(number.succ, range)
|
23
|
+
end
|
13
24
|
|
25
|
+
def <=>(other)
|
26
|
+
range <=> other.range && number <=> other.number
|
27
|
+
end
|
28
|
+
|
29
|
+
# allow for circular references
|
30
|
+
def range=(range)
|
31
|
+
@range = range
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
shared_examples 'IceNine::Freezer::Range.deep_freeze' do
|
14
37
|
it 'returns the object' do
|
15
38
|
should be(value)
|
16
39
|
end
|
@@ -27,4 +50,24 @@ describe IceNine::Freezer::Range, '.deep_freeze' do
|
|
27
50
|
expect(subject.end).to be_frozen
|
28
51
|
end
|
29
52
|
end
|
53
|
+
|
54
|
+
context 'with a Range' do
|
55
|
+
let(:value) { element_class.new(1)..element_class.new(100) }
|
56
|
+
|
57
|
+
context 'without a circular reference' do
|
58
|
+
it_behaves_like 'IceNine::Freezer::Range.deep_freeze'
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with a circular reference in the first element' do
|
62
|
+
before { value.begin.range = value }
|
63
|
+
|
64
|
+
it_behaves_like 'IceNine::Freezer::Range.deep_freeze'
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with a circular reference in the last element' do
|
68
|
+
before { value.end.range = value }
|
69
|
+
|
70
|
+
it_behaves_like 'IceNine::Freezer::Range.deep_freeze'
|
71
|
+
end
|
72
|
+
end
|
30
73
|
end
|
@@ -3,12 +3,12 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'ice_nine/support/recursion_guard'
|
5
5
|
|
6
|
-
describe IceNine::RecursionGuard, '
|
6
|
+
describe IceNine::RecursionGuard, '#guard' do
|
7
7
|
subject { object.guard(object_id, &method(:block)) }
|
8
8
|
|
9
|
-
let(:object) { IceNine::RecursionGuard }
|
10
|
-
let(:object_id) { 1
|
11
|
-
let(:return_value) { double('return_value')
|
9
|
+
let(:object) { IceNine::RecursionGuard.new }
|
10
|
+
let(:object_id) { 1 }
|
11
|
+
let(:return_value) { double('return_value') }
|
12
12
|
|
13
13
|
context 'when the block is not recursive' do
|
14
14
|
def block
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ice_nine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Kubb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- README.md
|
55
55
|
- Rakefile
|
56
56
|
- TODO
|
57
|
+
- benchmarks/speed.rb
|
57
58
|
- config/devtools.yml
|
58
59
|
- config/flay.yml
|
59
60
|
- config/flog.yml
|
@@ -86,6 +87,7 @@ files:
|
|
86
87
|
- spec/spec_helper.rb
|
87
88
|
- spec/support/config_alias.rb
|
88
89
|
- spec/unit/ice_nine/class_methods/deep_freeze_spec.rb
|
90
|
+
- spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb
|
89
91
|
- spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb
|
90
92
|
- spec/unit/ice_nine/freezer/class_methods/element_reader_spec.rb
|
91
93
|
- spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb
|
@@ -120,13 +122,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
122
|
version: '0'
|
121
123
|
requirements: []
|
122
124
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.
|
125
|
+
rubygems_version: 2.1.1
|
124
126
|
signing_key:
|
125
127
|
specification_version: 4
|
126
128
|
summary: Deep Freeze Ruby Objects
|
127
129
|
test_files:
|
128
130
|
- spec/integration/ice_nine/class_methods/deep_freeze_spec.rb
|
129
131
|
- spec/unit/ice_nine/class_methods/deep_freeze_spec.rb
|
132
|
+
- spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb
|
130
133
|
- spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb
|
131
134
|
- spec/unit/ice_nine/freezer/class_methods/element_reader_spec.rb
|
132
135
|
- spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb
|