deep_cloneable 1.2.4 → 1.3.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 CHANGED
@@ -4,7 +4,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
4
4
 
5
5
  == Requirements
6
6
 
7
- * Activerecord, tested with Rails 3.
7
+ * Activerecord, tested with AR 3 & 3.1.
8
8
 
9
9
  == Installation
10
10
 
@@ -60,6 +60,12 @@ If this is not an option for you, it is also possible to populate the dictionary
60
60
  === Cloning a model without an attribute or nested multiple attributes
61
61
  pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
62
62
 
63
+ == Contributors
64
+
65
+ * Michael He
66
+ * Indrek Juhkam
67
+ * Mart Karu
68
+
63
69
  == Note on Patches/Pull Requests
64
70
 
65
71
  * Fork the project.
@@ -72,4 +78,4 @@ If this is not an option for you, it is also possible to populate the dictionary
72
78
 
73
79
  == Copyright
74
80
 
75
- Copyright (c) 2010 Reinier de Lange. See LICENSE for details.
81
+ Copyright (c) 2011 Reinier de Lange. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.4
1
+ 1.3.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{deep_cloneable}
8
- s.version = "1.2.4"
8
+ s.version = "1.3.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{2011-06-15}
12
+ s.date = %q{2011-07-11}
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 = [
@@ -1,5 +1,7 @@
1
1
  class ActiveRecord::Base
2
2
  module DeepCloneable
3
+ @@rails31 = ActiveRecord::VERSION::MAJOR >= 3 && ActiveRecord::VERSION::MINOR > 0
4
+
3
5
  # clones an ActiveRecord model.
4
6
  # if passed the :include option, it will deep clone the given associations
5
7
  # if passed the :except option, it won't clone the given attributes
@@ -40,7 +42,9 @@ class ActiveRecord::Base
40
42
  # ==== Cloning a model without an attribute or nested multiple attributes
41
43
  # pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
42
44
  #
43
- def clone(options = {})
45
+ define_method (@@rails31 ? :dup : :clone) do |*args|
46
+ options = args[0] || {}
47
+
44
48
  dict = options[:dictionary]
45
49
  dict ||= {} if options.delete(:use_dictionary)
46
50
 
@@ -77,15 +81,17 @@ class ActiveRecord::Base
77
81
 
78
82
  cloned_object = case association_reflection.macro
79
83
  when :belongs_to, :has_one
80
- self.send(association) && self.send(association).clone(opts)
84
+ self.send(association) && self.send(association).send(__method__, opts)
81
85
  when :has_many, :has_and_belongs_to_many
82
- reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
83
- a.primary_key_name.to_s == association_reflection.primary_key_name.to_s
86
+ primary_key_name = (@@rails31 ? association_reflection.foreign_key : association_reflection.primary_key_name).to_s
87
+
88
+ reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
89
+ a.send(@@rails31 ? :foreign_key : :primary_key_name).to_s == primary_key_name
84
90
  end.try(:name)
85
91
 
86
92
  self.send(association).collect do |obj|
87
- tmp = obj.clone(opts)
88
- tmp.send("#{association_reflection.primary_key_name.to_s}=", nil)
93
+ tmp = obj.send(__method__, opts)
94
+ tmp.send("#{primary_key_name}=", nil)
89
95
  tmp.send("#{reverse_association_name.to_s}=", kopy) if reverse_association_name
90
96
  tmp
91
97
  end
@@ -2,8 +2,10 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  class TestDeepCloneable < Test::Unit::TestCase
4
4
  load_schema
5
+
6
+ @@clone_method = ActiveRecord::VERSION::MAJOR >= 3 && ActiveRecord::VERSION::MINOR > 0 ? :dup : :clone
5
7
 
6
- def setup
8
+ def setup
7
9
  @jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
8
10
  @polly = Parrot.create(:name => 'Polly', :pirate => @jack)
9
11
  @john = Matey.create(:name => 'John', :pirate => @jack)
@@ -12,109 +14,109 @@ class TestDeepCloneable < Test::Unit::TestCase
12
14
  @ship = BattleShip.create(:name => 'Black Pearl', :pirates => [@jack])
13
15
  end
14
16
 
15
- def test_single_clone_exception
16
- clone = @jack.clone(:except => :name)
17
- assert clone.save
18
- assert_equal @jack.name, @jack.clone.name # Old behaviour
19
- assert_nil clone.name
20
- assert_equal @jack.nick_name, clone.nick_name
17
+ def test_single_dup_exception
18
+ dup = @jack.send(@@clone_method, :except => :name)
19
+ assert dup.save
20
+ assert_equal @jack.name, @jack.send(@@clone_method).name # Old behaviour
21
+ assert_nil dup.name
22
+ assert_equal @jack.nick_name, dup.nick_name
21
23
  end
22
24
 
23
- def test_multiple_clone_exception
24
- clone = @jack.clone(:except => [:name, :nick_name])
25
- assert clone.save
26
- assert_nil clone.name
27
- assert_equal 'no nickname', clone.nick_name
28
- assert_equal @jack.age, clone.age
25
+ def test_multiple_dup_exception
26
+ dup = @jack.send(@@clone_method, :except => [:name, :nick_name])
27
+ assert dup.save
28
+ assert_nil dup.name
29
+ assert_equal 'no nickname', dup.nick_name
30
+ assert_equal @jack.age, dup.age
29
31
  end
30
32
 
31
33
  def test_single_include_association
32
- clone = @jack.clone(:include => :mateys)
33
- assert clone.save
34
- assert_equal 1, clone.mateys.size
34
+ dup = @jack.send(@@clone_method, :include => :mateys)
35
+ assert dup.save
36
+ assert_equal 1, dup.mateys.size
35
37
  end
36
38
 
37
39
  def test_single_include_belongs_to_polymorphic_association
38
- clone = @jack.clone(:include => :ship)
39
- assert clone.save
40
- assert_not_nil clone.ship
41
- assert_not_equal @jack.ship, clone.ship
40
+ dup = @jack.send(@@clone_method, :include => :ship)
41
+ assert dup.save
42
+ assert_not_nil dup.ship
43
+ assert_not_equal @jack.ship, dup.ship
42
44
  end
43
45
 
44
46
  def test_single_include_has_many_polymorphic_association
45
- clone = @ship.clone(:include => :pirates)
46
- assert clone.save
47
- assert clone.pirates.any?
47
+ dup = @ship.send(@@clone_method, :include => :pirates)
48
+ assert dup.save
49
+ assert dup.pirates.any?
48
50
  end
49
51
 
50
52
  def test_multiple_include_association
51
- clone = @jack.clone(:include => [:mateys, :treasures])
52
- assert clone.save
53
- assert_equal 1, clone.mateys.size
54
- assert_equal 1, clone.treasures.size
53
+ dup = @jack.send(@@clone_method, :include => [:mateys, :treasures])
54
+ assert dup.save
55
+ assert_equal 1, dup.mateys.size
56
+ assert_equal 1, dup.treasures.size
55
57
  end
56
58
 
57
59
  def test_deep_include_association
58
- clone = @jack.clone(:include => {:treasures => :gold_pieces})
59
- assert clone.save
60
- assert_equal 1, clone.treasures.size
61
- assert_equal 1, clone.gold_pieces.size
60
+ dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces})
61
+ assert dup.save
62
+ assert_equal 1, dup.treasures.size
63
+ assert_equal 1, dup.gold_pieces.size
62
64
  end
63
65
 
64
66
  def test_include_association_assignments
65
- clone = @jack.clone(:include => :treasures)
67
+ dup = @jack.send(@@clone_method, :include => :treasures)
66
68
 
67
- clone.treasures.each do |treasure|
68
- assert_equal clone, treasure.pirate
69
+ dup.treasures.each do |treasure|
70
+ assert_equal dup, treasure.pirate
69
71
  end
70
72
  end
71
73
 
72
74
  def test_multiple_and_deep_include_association
73
- clone = @jack.clone(:include => {:treasures => :gold_pieces, :mateys => {}})
74
- assert clone.save
75
- assert_equal 1, clone.treasures.size
76
- assert_equal 1, clone.gold_pieces.size
77
- assert_equal 1, clone.mateys.size
75
+ dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces, :mateys => {}})
76
+ assert dup.save
77
+ assert_equal 1, dup.treasures.size
78
+ assert_equal 1, dup.gold_pieces.size
79
+ assert_equal 1, dup.mateys.size
78
80
  end
79
81
 
80
82
  def test_multiple_and_deep_include_association_with_array
81
- clone = @jack.clone(:include => [{:treasures => :gold_pieces}, :mateys])
82
- assert clone.save
83
- assert_equal 1, clone.treasures.size
84
- assert_equal 1, clone.gold_pieces.size
85
- assert_equal 1, clone.mateys.size
83
+ dup = @jack.send(@@clone_method, :include => [{:treasures => :gold_pieces}, :mateys])
84
+ assert dup.save
85
+ assert_equal 1, dup.treasures.size
86
+ assert_equal 1, dup.gold_pieces.size
87
+ assert_equal 1, dup.mateys.size
86
88
  end
87
89
 
88
90
  def test_with_belongs_to_relation
89
- clone = @jack.clone(:include => :parrot)
90
- assert clone.save
91
- assert_not_equal clone.parrot, @jack.parrot
91
+ dup = @jack.send(@@clone_method, :include => :parrot)
92
+ assert dup.save
93
+ assert_not_equal dup.parrot, @jack.parrot
92
94
  end
93
95
 
94
96
  def test_should_pass_nested_exceptions
95
- clone = @jack.clone(:include => :parrot, :except => [:name, { :parrot => [:name] }])
96
- assert clone.save
97
- assert_not_equal clone.parrot, @jack.parrot
97
+ dup = @jack.send(@@clone_method, :include => :parrot, :except => [:name, { :parrot => [:name] }])
98
+ assert dup.save
99
+ assert_not_equal dup.parrot, @jack.parrot
98
100
  assert_not_nil @jack.parrot.name
99
- assert_nil clone.parrot.name
101
+ assert_nil dup.parrot.name
100
102
  end
101
103
 
102
- def test_should_not_double_clone_when_using_dictionary
104
+ def test_should_not_double_dup_when_using_dictionary
103
105
  current_matey_count = Matey.count
104
- clone = @jack.clone(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
105
- clone.save!
106
+ dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
107
+ dup.save!
106
108
 
107
109
  assert_equal current_matey_count + 1, Matey.count
108
110
  end
109
111
 
110
- def test_should_not_double_clone_when_using_manual_dictionary
112
+ def test_should_not_double_dup_when_using_manual_dictionary
111
113
  current_matey_count = Matey.count
112
114
 
113
115
  dict = { :mateys => {} }
114
- @jack.mateys.each{|m| dict[:mateys][m] = m.clone }
116
+ @jack.mateys.each{|m| dict[:mateys][m] = m.send(@@clone_method) }
115
117
 
116
- clone = @jack.clone(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
117
- clone.save!
118
+ dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :dictionary => dict)
119
+ dup.save!
118
120
 
119
121
  assert_equal current_matey_count + 1, Matey.count
120
122
  end
@@ -123,19 +125,19 @@ class TestDeepCloneable < Test::Unit::TestCase
123
125
  @human = Animal::Human.create :name => "Michael"
124
126
  @pig = Animal::Pig.create :human => @human, :name => 'big pig'
125
127
 
126
- clone_human = @human.clone :include => [:pigs]
127
- assert clone_human.save
128
- assert_equal 1, clone_human.pigs.count
128
+ dup_human = @human.send(@@clone_method, :include => [:pigs])
129
+ assert dup_human.save
130
+ assert_equal 1, dup_human.pigs.count
129
131
 
130
132
  @human2 = Animal::Human.create :name => "John"
131
133
  @pig2 = @human2.pigs.create :name => 'small pig'
132
134
 
133
- clone_human_2 = @human.clone :include => [:pigs]
134
- assert clone_human_2.save
135
- assert_equal 1, clone_human_2.pigs.count
135
+ dup_human_2 = @human.send(@@clone_method, :include => [:pigs])
136
+ assert dup_human_2.save
137
+ assert_equal 1, dup_human_2.pigs.count
136
138
  end
137
139
 
138
- def test_should_clone_many_to_many_associations
140
+ def test_should_dup_many_to_many_associations
139
141
  @human = Animal::Human.create :name => "Michael"
140
142
  @human2 = Animal::Human.create :name => "Jack"
141
143
  @chicken1 = Animal::Chicken.create :name => 'Chick1'
@@ -143,9 +145,9 @@ class TestDeepCloneable < Test::Unit::TestCase
143
145
  @human.chickens << [@chicken1, @chicken2]
144
146
  @human2.chickens << [@chicken1, @chicken2]
145
147
 
146
- clone_human = @human.clone :include => :ownerships
147
- assert clone_human.save
148
- assert_equal 2, clone_human.chickens.count
148
+ dup_human = @human.send(@@clone_method, :include => :ownerships)
149
+ assert dup_human.save
150
+ assert_equal 2, dup_human.chickens.count
149
151
  end
150
152
 
151
153
  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: 23
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 2
9
- - 4
10
- version: 1.2.4
8
+ - 3
9
+ - 0
10
+ version: 1.3.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: 2011-06-15 00:00:00 +02:00
18
+ date: 2011-07-11 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21