deep_clonable 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -0
- data/deep_clonable.gemspec +13 -18
- data/lib/deep_clonable.rb +32 -23
- data/test/deep_clonable_test.rb +78 -19
- metadata +22 -11
- data/VERSION.yml +0 -5
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
data/deep_clonable.gemspec
CHANGED
@@ -1,46 +1,41 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{deep_clonable}
|
8
|
-
s.version = "1.0
|
8
|
+
s.version = "1.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Balthrop"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-06-02}
|
13
13
|
s.description = %q{ Add support for deep cloning to objects}
|
14
14
|
s.email = %q{code@justinbalthrop.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
|
17
|
+
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
"LICENSE",
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"deep_clonable.gemspec",
|
25
|
+
"lib/deep_clonable.rb",
|
26
|
+
"test/deep_clonable_test.rb",
|
27
|
+
"test/test_helper.rb"
|
28
28
|
]
|
29
29
|
s.homepage = %q{http://github.com/ninjudd/deep_clonable}
|
30
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
31
30
|
s.require_paths = ["lib"]
|
32
|
-
s.rubygems_version = %q{1.3.
|
31
|
+
s.rubygems_version = %q{1.3.7}
|
33
32
|
s.summary = %q{Add support for deep cloning to objects}
|
34
|
-
s.test_files = [
|
35
|
-
"test/deep_clonable_test.rb",
|
36
|
-
"test/test_helper.rb"
|
37
|
-
]
|
38
33
|
|
39
34
|
if s.respond_to? :specification_version then
|
40
35
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
41
36
|
s.specification_version = 3
|
42
37
|
|
43
|
-
if Gem::Version.new(Gem::
|
38
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
39
|
else
|
45
40
|
end
|
46
41
|
else
|
data/lib/deep_clonable.rb
CHANGED
@@ -8,25 +8,37 @@ end
|
|
8
8
|
module DeepClonable
|
9
9
|
module InstanceMethods
|
10
10
|
def clone
|
11
|
-
|
12
|
-
cloned_object.
|
13
|
-
cloned_object
|
11
|
+
was_frozen = frozen?
|
12
|
+
cloned_object = super.dup
|
13
|
+
cloned_object = yield(cloned_object) if block_given?
|
14
|
+
was_frozen ? cloned_object.freeze : cloned_object
|
14
15
|
end
|
15
|
-
|
16
|
-
def dup
|
17
|
-
cloned_object = super
|
18
|
-
cloned_object.
|
16
|
+
|
17
|
+
def dup(method = :dup)
|
18
|
+
cloned_object = super()
|
19
|
+
cloned_object.update_vars(deep_vars, method)
|
19
20
|
cloned_object
|
20
21
|
end
|
21
22
|
|
22
|
-
|
23
|
+
alias old_freeze freeze
|
24
|
+
|
25
|
+
def freeze
|
26
|
+
dup(:freeze).old_freeze
|
27
|
+
end
|
28
|
+
|
29
|
+
# You can override deep_vars in your class to specify which instance_variables should be deep cloned.
|
23
30
|
# As it is, all Arrays and Hashes are deep cloned.
|
24
|
-
def
|
25
|
-
instance_variables.
|
26
|
-
value = instance_variable_get(
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
def deep_vars
|
32
|
+
instance_variables.select do |var|
|
33
|
+
value = instance_variable_get(var)
|
34
|
+
value.kind_of?(Array) or value.kind_of?(Hash) or value.kind_of?(DeepClonable::InstanceMethods)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_vars(vars, method)
|
39
|
+
vars.each do |var|
|
40
|
+
value = instance_variable_get(var)
|
41
|
+
instance_variable_set(var, value.send(method))
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
@@ -34,8 +46,8 @@ module DeepClonable
|
|
34
46
|
module ClassMethods
|
35
47
|
# Use this to define cloning version of the given in-place methods.
|
36
48
|
#
|
37
|
-
# This method supports a common idiom where you create in-place and
|
38
|
-
# cloning versions of most operations. This method allows you to
|
49
|
+
# This method supports a common idiom where you create in-place and
|
50
|
+
# cloning versions of most operations. This method allows you to
|
39
51
|
# define only the in-place version (with the trailing bang (!),
|
40
52
|
# that part is important) and specify the cloning versions by name
|
41
53
|
# using this method.
|
@@ -43,13 +55,10 @@ module DeepClonable
|
|
43
55
|
clone_method_name = clone_method_name.to_s.gsub(/\!$/,'')
|
44
56
|
method_name ||= "#{clone_method_name}!"
|
45
57
|
class_eval %{
|
46
|
-
def #{clone_method_name}(*args)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
yield object
|
51
|
-
else
|
52
|
-
object
|
58
|
+
def #{clone_method_name}(*args, &block)
|
59
|
+
self.clone do |object|
|
60
|
+
object.#{method_name}(*args)
|
61
|
+
block ? block.call(object) : object
|
53
62
|
end
|
54
63
|
end
|
55
64
|
}
|
data/test/deep_clonable_test.rb
CHANGED
@@ -1,41 +1,100 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
3
|
class TestClass
|
4
4
|
deep_clonable
|
5
|
-
|
6
|
-
attr_reader :num
|
7
|
-
|
8
|
-
def initialize(
|
9
|
-
@num
|
5
|
+
|
6
|
+
attr_reader :num, :hash, :array
|
7
|
+
|
8
|
+
def initialize(num, hash, array)
|
9
|
+
@num = num
|
10
|
+
@hash = hash
|
11
|
+
@array = array
|
10
12
|
end
|
11
|
-
|
13
|
+
|
12
14
|
clone_method :+, :add!
|
13
15
|
def add!(other)
|
14
16
|
@num += other.num
|
17
|
+
@hash.merge!(other.hash)
|
18
|
+
@array.concat(other.array)
|
15
19
|
end
|
16
20
|
|
17
21
|
clone_method :invert
|
18
22
|
def invert!
|
19
|
-
@num
|
23
|
+
@num = -(@num)
|
24
|
+
@hash = @hash.invert
|
25
|
+
@array.reverse!
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
23
29
|
class DeepClonableTest < Test::Unit::TestCase
|
24
|
-
should
|
25
|
-
a = TestClass.new(10)
|
30
|
+
should "clone method" do
|
31
|
+
a = TestClass.new(10, {:a => 1}, [1,2,3])
|
26
32
|
b = a.invert
|
27
|
-
|
28
|
-
assert_equal
|
29
|
-
assert_equal
|
33
|
+
|
34
|
+
assert_equal(10, a.num)
|
35
|
+
assert_equal({:a => 1}, a.hash)
|
36
|
+
assert_equal([1,2,3], a.array)
|
37
|
+
|
38
|
+
assert_equal(-10, b.num)
|
39
|
+
assert_equal({1 => :a}, b.hash)
|
40
|
+
assert_equal([3,2,1], b.array)
|
30
41
|
end
|
31
42
|
|
32
43
|
should 'clone method with rename' do
|
33
|
-
a = TestClass.new(10)
|
34
|
-
b = TestClass.new(20)
|
44
|
+
a = TestClass.new(10, {:a => 1}, [1])
|
45
|
+
b = TestClass.new(20, {:b => 2}, [2,3])
|
35
46
|
c = a + b
|
36
|
-
|
37
|
-
assert_equal
|
38
|
-
assert_equal
|
39
|
-
assert_equal
|
47
|
+
|
48
|
+
assert_equal(10, a.num)
|
49
|
+
assert_equal({:a => 1}, a.hash)
|
50
|
+
assert_equal([1], a.array)
|
51
|
+
|
52
|
+
assert_equal(20, b.num)
|
53
|
+
assert_equal({:b => 2}, b.hash)
|
54
|
+
assert_equal([2,3], b.array)
|
55
|
+
|
56
|
+
assert_equal(30, c.num)
|
57
|
+
assert_equal({:a => 1, :b => 2}, c.hash)
|
58
|
+
assert_equal([1,2,3], c.array)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "return a frozen object when cloning a frozen object" do
|
62
|
+
a = TestClass.new(10, {:a => 1}, [1,2,3]).freeze
|
63
|
+
|
64
|
+
assert_raises(TypeError) do
|
65
|
+
a.invert!
|
66
|
+
end
|
67
|
+
|
68
|
+
b = a.invert
|
69
|
+
|
70
|
+
assert_equal(10, a.num)
|
71
|
+
assert_equal({:a => 1}, a.hash)
|
72
|
+
assert_equal([1,2,3], a.array)
|
73
|
+
|
74
|
+
assert_equal(-10, b.num)
|
75
|
+
assert_equal({1 => :a}, b.hash)
|
76
|
+
assert_equal([3,2,1], b.array)
|
77
|
+
|
78
|
+
assert a.frozen?
|
79
|
+
assert b.frozen?
|
80
|
+
assert a.clone.frozen?
|
81
|
+
end
|
82
|
+
|
83
|
+
should "unfreeze an object when duping" do
|
84
|
+
a = TestClass.new(10, {:a => 1}, [1,2,3]).freeze
|
85
|
+
b = a.dup
|
86
|
+
|
87
|
+
assert a.frozen?
|
88
|
+
assert !b.frozen?
|
89
|
+
|
90
|
+
b.invert!
|
91
|
+
|
92
|
+
assert_equal(10, a.num)
|
93
|
+
assert_equal({:a => 1}, a.hash)
|
94
|
+
assert_equal([1,2,3], a.array)
|
95
|
+
|
96
|
+
assert_equal(-10, b.num)
|
97
|
+
assert_equal({1 => :a}, b.hash)
|
98
|
+
assert_equal([3,2,1], b.array)
|
40
99
|
end
|
41
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep_clonable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 1.1.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Justin Balthrop
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2011-06-02 00:00:00 -07:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -26,7 +32,7 @@ files:
|
|
26
32
|
- LICENSE
|
27
33
|
- README.rdoc
|
28
34
|
- Rakefile
|
29
|
-
- VERSION
|
35
|
+
- VERSION
|
30
36
|
- deep_clonable.gemspec
|
31
37
|
- lib/deep_clonable.rb
|
32
38
|
- test/deep_clonable_test.rb
|
@@ -36,29 +42,34 @@ homepage: http://github.com/ninjudd/deep_clonable
|
|
36
42
|
licenses: []
|
37
43
|
|
38
44
|
post_install_message:
|
39
|
-
rdoc_options:
|
40
|
-
|
45
|
+
rdoc_options: []
|
46
|
+
|
41
47
|
require_paths:
|
42
48
|
- lib
|
43
49
|
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
44
51
|
requirements:
|
45
52
|
- - ">="
|
46
53
|
- !ruby/object:Gem::Version
|
54
|
+
hash: 3
|
55
|
+
segments:
|
56
|
+
- 0
|
47
57
|
version: "0"
|
48
|
-
version:
|
49
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
50
60
|
requirements:
|
51
61
|
- - ">="
|
52
62
|
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
53
66
|
version: "0"
|
54
|
-
version:
|
55
67
|
requirements: []
|
56
68
|
|
57
69
|
rubyforge_project:
|
58
|
-
rubygems_version: 1.3.
|
70
|
+
rubygems_version: 1.3.7
|
59
71
|
signing_key:
|
60
72
|
specification_version: 3
|
61
73
|
summary: Add support for deep cloning to objects
|
62
|
-
test_files:
|
63
|
-
|
64
|
-
- test/test_helper.rb
|
74
|
+
test_files: []
|
75
|
+
|