deep_cloneable 1.0.0 → 1.1.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.
- data/README.rdoc +9 -5
- data/VERSION +1 -1
- data/deep_cloneable.gemspec +2 -2
- data/lib/deep_cloneable.rb +33 -17
- data/test/test_deep_cloneable.rb +8 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -25,12 +25,7 @@ And include the gem in your apps config
|
|
25
25
|
./script/plugin install git://github.com/moiristo/deep_cloneable.git
|
26
26
|
|
27
27
|
== Example
|
28
|
-
|
29
|
-
=== Cloning a model without an attribute
|
30
|
-
pirate.clone :except => :name
|
31
28
|
|
32
|
-
=== Cloning a model without multiple attributes
|
33
|
-
pirate.clone :except => [:name, :nick_name]
|
34
29
|
=== Cloning one single association
|
35
30
|
pirate.clone :include => :mateys
|
36
31
|
|
@@ -42,6 +37,15 @@ And include the gem in your apps config
|
|
42
37
|
|
43
38
|
=== Cloning really deep with multiple associations
|
44
39
|
pirate.clone :include => [:mateys, {:treasures => :gold_pieces}]
|
40
|
+
|
41
|
+
=== Cloning a model without an attribute
|
42
|
+
pirate.clone :except => :name
|
43
|
+
|
44
|
+
=== Cloning a model without multiple attributes
|
45
|
+
pirate.clone :except => [:name, :nick_name]
|
46
|
+
|
47
|
+
=== Cloning a model without an attribute or nested multiple attributes
|
48
|
+
pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
|
45
49
|
|
46
50
|
== Note on Patches/Pull Requests
|
47
51
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
data/deep_cloneable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{deep_cloneable}
|
8
|
-
s.version = "1.
|
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 = ["Reinier de Lange"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-19}
|
13
13
|
s.description = %q{Extends the functionality of ActiveRecord::Base#clone to perform a deep clone that includes user specified associations. }
|
14
14
|
s.email = %q{r.j.delange@nedforce.nl}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/deep_cloneable.rb
CHANGED
@@ -6,30 +6,37 @@ class ActiveRecord::Base
|
|
6
6
|
#
|
7
7
|
# === Usage:
|
8
8
|
#
|
9
|
-
# ==== Cloning a model without an attribute
|
10
|
-
# pirate.clone :except => :name
|
11
|
-
#
|
12
|
-
# ==== Cloning a model without multiple attributes
|
13
|
-
# pirate.clone :except => [:name, :nick_name]
|
14
9
|
# ==== Cloning one single association
|
15
|
-
#
|
16
|
-
#
|
10
|
+
# pirate.clone :include => :mateys
|
11
|
+
#
|
17
12
|
# ==== Cloning multiple associations
|
18
|
-
#
|
19
|
-
#
|
13
|
+
# pirate.clone :include => [:mateys, :treasures]
|
14
|
+
#
|
20
15
|
# ==== Cloning really deep
|
21
|
-
#
|
22
|
-
#
|
16
|
+
# pirate.clone :include => {:treasures => :gold_pieces}
|
17
|
+
#
|
23
18
|
# ==== Cloning really deep with multiple associations
|
24
|
-
#
|
19
|
+
# pirate.clone :include => [:mateys, {:treasures => :gold_pieces}]
|
20
|
+
#
|
21
|
+
# ==== Cloning a model without an attribute
|
22
|
+
# pirate.clone :except => :name
|
23
|
+
#
|
24
|
+
# ==== Cloning a model without multiple attributes
|
25
|
+
# pirate.clone :except => [:name, :nick_name]
|
26
|
+
#
|
27
|
+
# ==== Cloning a model without an attribute or nested multiple attributes
|
28
|
+
# pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
|
25
29
|
#
|
26
30
|
def clone(options = {})
|
27
31
|
kopy = super()
|
28
|
-
|
32
|
+
|
33
|
+
deep_exceptions = {}
|
29
34
|
if options[:except]
|
30
|
-
|
31
|
-
|
35
|
+
exceptions = options[:except].nil? ? [] : [options[:except]].flatten
|
36
|
+
exceptions.each do |attribute|
|
37
|
+
kopy.send(:write_attribute, attribute, attributes_from_column_definition[attribute.to_s]) unless attribute.kind_of?(Hash)
|
32
38
|
end
|
39
|
+
deep_exceptions = exceptions.select{|e| e.kind_of?(Hash) }.inject({}){|m,h| m.merge(h) }
|
33
40
|
end
|
34
41
|
|
35
42
|
if options[:include]
|
@@ -38,12 +45,21 @@ class ActiveRecord::Base
|
|
38
45
|
deep_associations = association[association.keys.first]
|
39
46
|
association = association.keys.first
|
40
47
|
end
|
48
|
+
|
41
49
|
opts = deep_associations.blank? ? {} : {:include => deep_associations}
|
42
|
-
|
50
|
+
opts.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
|
51
|
+
|
52
|
+
association_reflection = self.class.reflect_on_association(association)
|
53
|
+
cloned_object = case association_reflection.macro
|
43
54
|
when :belongs_to, :has_one
|
44
55
|
self.send(association) && self.send(association).clone(opts)
|
45
56
|
when :has_many, :has_and_belongs_to_many
|
46
|
-
|
57
|
+
fk = association_reflection.options[:foreign_key] || self.class.to_s.underscore
|
58
|
+
self.send(association).collect do |obj|
|
59
|
+
tmp = obj.clone(opts)
|
60
|
+
tmp.send("#{fk}=", kopy)
|
61
|
+
tmp
|
62
|
+
end
|
47
63
|
end
|
48
64
|
kopy.send("#{association}=", cloned_object)
|
49
65
|
end
|
data/test/test_deep_cloneable.rb
CHANGED
@@ -68,4 +68,12 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
68
68
|
assert clone.save
|
69
69
|
assert_not_equal clone.parrot, @jack.parrot
|
70
70
|
end
|
71
|
+
|
72
|
+
def test_should_pass_nested_exceptions
|
73
|
+
clone = @jack.clone(:include => :parrot, :except => [:name, { :parrot => [:name] }])
|
74
|
+
assert clone.save
|
75
|
+
assert_not_equal clone.parrot, @jack.parrot
|
76
|
+
assert_not_nil @jack.parrot.name
|
77
|
+
assert_nil clone.parrot.name
|
78
|
+
end
|
71
79
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep_cloneable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Reinier de Lange
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-19 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|