deep_cloneable 1.4.0 → 1.4.1

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/Gemfile CHANGED
@@ -1,9 +1,10 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gemspec
4
-
5
3
  gem 'rails'
6
- gem 'jeweler'
4
+
5
+ group :development do
6
+ gem 'jeweler'
7
+ end
7
8
 
8
9
  group :test do
9
10
  gem 'sqlite3'
data/Gemfile.lock CHANGED
@@ -1,8 +1,3 @@
1
- PATH
2
- remote: .
3
- specs:
4
- deep_cloneable (1.3.1)
5
-
6
1
  GEM
7
2
  remote: http://rubygems.org/
8
3
  specs:
@@ -94,7 +89,6 @@ PLATFORMS
94
89
  ruby
95
90
 
96
91
  DEPENDENCIES
97
- deep_cloneable!
98
92
  jeweler
99
93
  rails
100
94
  sqlite3
data/README.rdoc CHANGED
@@ -12,7 +12,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
12
12
 
13
13
  * In your Gemfile:
14
14
 
15
- gem 'deep_cloneable', '~> 1.3.1'
15
+ gem 'deep_cloneable', '~> 1.4.0'
16
16
 
17
17
  == Example
18
18
 
@@ -62,6 +62,8 @@ If this is not an option for you, it is also possible to populate the dictionary
62
62
  * Mart Karu
63
63
  * Rolf Timmermans
64
64
  * Ilya Kuzmin
65
+ * zozi
66
+ * fractious
65
67
 
66
68
  == Note on Patches/Pull Requests
67
69
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.4.1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "deep_cloneable"
8
- s.version = "1.4.0"
8
+ s.version = "1.4.1"
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 = "2012-04-02"
12
+ s.date = "2012-07-23"
13
13
  s.description = "Extends the functionality of ActiveRecord::Base#clone to perform a deep clone that includes user specified associations. "
14
14
  s.email = "r.j.delange@nedforce.nl"
15
15
  s.extra_rdoc_files = [
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  "init.rb",
29
29
  "lib/deep_cloneable.rb",
30
30
  "test/database.yml",
31
+ "test/models.rb",
31
32
  "test/schema.rb",
32
33
  "test/test_deep_cloneable.rb",
33
34
  "test/test_helper.rb"
@@ -41,16 +42,13 @@ Gem::Specification.new do |s|
41
42
  s.specification_version = 3
42
43
 
43
44
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
- s.add_runtime_dependency(%q<deep_cloneable>, [">= 0"])
45
45
  s.add_runtime_dependency(%q<rails>, [">= 0"])
46
- s.add_runtime_dependency(%q<jeweler>, [">= 0"])
46
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
47
47
  else
48
- s.add_dependency(%q<deep_cloneable>, [">= 0"])
49
48
  s.add_dependency(%q<rails>, [">= 0"])
50
49
  s.add_dependency(%q<jeweler>, [">= 0"])
51
50
  end
52
51
  else
53
- s.add_dependency(%q<deep_cloneable>, [">= 0"])
54
52
  s.add_dependency(%q<rails>, [">= 0"])
55
53
  s.add_dependency(%q<jeweler>, [">= 0"])
56
54
  end
@@ -101,7 +101,7 @@ class ActiveRecord::Base
101
101
  cloned_object = case association_reflection.macro
102
102
  when :belongs_to, :has_one
103
103
  self.send(association) && self.send(association).send(__method__, opts, &block)
104
- when :has_many, :has_and_belongs_to_many
104
+ when :has_many
105
105
  primary_key_name = (@@rails31 ? association_reflection.foreign_key : association_reflection.primary_key_name).to_s
106
106
 
107
107
  reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
@@ -114,7 +114,19 @@ class ActiveRecord::Base
114
114
  tmp.send("#{reverse_association_name.to_s}=", kopy) if reverse_association_name
115
115
  tmp
116
116
  end
117
- end
117
+ when :has_and_belongs_to_many
118
+ primary_key_name = (@@rails31 ? association_reflection.foreign_key : association_reflection.primary_key_name).to_s
119
+
120
+ reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
121
+ (a.macro == :has_and_belongs_to_many) && (a.association_foreign_key.to_s == primary_key_name)
122
+ end.try(:name)
123
+
124
+ self.send(association).collect do |obj|
125
+ obj.send(reverse_association_name).target << kopy
126
+ obj
127
+ end
128
+ end
129
+
118
130
  kopy.send("#{association}=", cloned_object)
119
131
  end
120
132
  end
data/test/models.rb ADDED
@@ -0,0 +1,53 @@
1
+ module Animal
2
+ class Human < ActiveRecord::Base
3
+ has_many :pigs
4
+
5
+ has_many :ownerships
6
+ has_many :chickens, :through => :ownerships
7
+ end
8
+ class Pig < ActiveRecord::Base
9
+ belongs_to :human
10
+ end
11
+
12
+ class Chicken < ActiveRecord::Base
13
+ has_many :ownerships
14
+ has_many :humans, :through => :ownerships
15
+ end
16
+
17
+ class Ownership < ActiveRecord::Base
18
+ belongs_to :human
19
+ belongs_to :chicken
20
+
21
+ validates_uniqueness_of :chicken_id, :scope => :human_id
22
+ end
23
+ end
24
+
25
+ class GoldPiece < ActiveRecord::Base; belongs_to :treasure end
26
+ class Matey < ActiveRecord::Base; belongs_to :pirate end
27
+ class Parrot < ActiveRecord::Base; belongs_to :pirate; attr_accessor :cloned_from_id end
28
+ class BattleShip < ActiveRecord::Base; has_many :pirates, :as => :ship end
29
+
30
+ class Pirate < ActiveRecord::Base
31
+ belongs_to :ship, :polymorphic => true
32
+
33
+ has_many :mateys
34
+ has_many :treasures, :foreign_key => 'owner'
35
+ has_many :gold_pieces, :through => :treasures
36
+ has_one :parrot
37
+
38
+ attr_accessor :cloned_from_id
39
+ end
40
+
41
+ class Treasure < ActiveRecord::Base
42
+ belongs_to :pirate, :foreign_key => :owner
43
+ belongs_to :matey
44
+ has_many :gold_pieces
45
+ end
46
+
47
+ class Person < ActiveRecord::Base
48
+ has_and_belongs_to_many :cars
49
+ end
50
+
51
+ class Car < ActiveRecord::Base
52
+ has_and_belongs_to_many :people
53
+ end
data/test/schema.rb CHANGED
@@ -47,6 +47,19 @@ ActiveRecord::Schema.define(:version => 1) do
47
47
  create_table :ownerships, :force => true do |t|
48
48
  t.column :human_id, :integer
49
49
  t.column :chicken_id, :integer
50
- end
50
+ end
51
+
52
+ create_table :cars, :force => true do |t|
53
+ t.column :name, :string
54
+ end
55
+
56
+ create_table :people, :force => true do |t|
57
+ t.column :name, :string
58
+ end
59
+
60
+ create_table :cars_people, :id => false, :force => true do |t|
61
+ t.column :car_id, :integer
62
+ t.column :person_id, :integer
63
+ end
51
64
 
52
65
  end
@@ -16,6 +16,7 @@ class TestDeepCloneable < Test::Unit::TestCase
16
16
 
17
17
  def test_single_dup_exception
18
18
  dup = @jack.send(@@clone_method, :except => :name)
19
+ assert dup.new_record?
19
20
  assert dup.save
20
21
  assert_equal @jack.name, @jack.send(@@clone_method).name # Old behaviour
21
22
  assert_nil dup.name
@@ -24,6 +25,7 @@ class TestDeepCloneable < Test::Unit::TestCase
24
25
 
25
26
  def test_multiple_dup_exception
26
27
  dup = @jack.send(@@clone_method, :except => [:name, :nick_name])
28
+ assert dup.new_record?
27
29
  assert dup.save
28
30
  assert_nil dup.name
29
31
  assert_equal 'no nickname', dup.nick_name
@@ -32,12 +34,14 @@ class TestDeepCloneable < Test::Unit::TestCase
32
34
 
33
35
  def test_single_include_association
34
36
  dup = @jack.send(@@clone_method, :include => :mateys)
37
+ assert dup.new_record?
35
38
  assert dup.save
36
39
  assert_equal 1, dup.mateys.size
37
40
  end
38
41
 
39
42
  def test_single_include_belongs_to_polymorphic_association
40
43
  dup = @jack.send(@@clone_method, :include => :ship)
44
+ assert dup.new_record?
41
45
  assert dup.save
42
46
  assert_not_nil dup.ship
43
47
  assert_not_equal @jack.ship, dup.ship
@@ -45,12 +49,14 @@ class TestDeepCloneable < Test::Unit::TestCase
45
49
 
46
50
  def test_single_include_has_many_polymorphic_association
47
51
  dup = @ship.send(@@clone_method, :include => :pirates)
52
+ assert dup.new_record?
48
53
  assert dup.save
49
54
  assert dup.pirates.any?
50
55
  end
51
56
 
52
57
  def test_multiple_include_association
53
58
  dup = @jack.send(@@clone_method, :include => [:mateys, :treasures])
59
+ assert dup.new_record?
54
60
  assert dup.save
55
61
  assert_equal 1, dup.mateys.size
56
62
  assert_equal 1, dup.treasures.size
@@ -58,6 +64,7 @@ class TestDeepCloneable < Test::Unit::TestCase
58
64
 
59
65
  def test_deep_include_association
60
66
  dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces})
67
+ assert dup.new_record?
61
68
  assert dup.save
62
69
  assert_equal 1, dup.treasures.size
63
70
  assert_equal 1, dup.gold_pieces.size
@@ -65,6 +72,7 @@ class TestDeepCloneable < Test::Unit::TestCase
65
72
 
66
73
  def test_include_association_assignments
67
74
  dup = @jack.send(@@clone_method, :include => :treasures)
75
+ assert dup.new_record?
68
76
 
69
77
  dup.treasures.each do |treasure|
70
78
  assert_equal dup, treasure.pirate
@@ -73,6 +81,7 @@ class TestDeepCloneable < Test::Unit::TestCase
73
81
 
74
82
  def test_multiple_and_deep_include_association
75
83
  dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces, :mateys => {}})
84
+ assert dup.new_record?
76
85
  assert dup.save
77
86
  assert_equal 1, dup.treasures.size
78
87
  assert_equal 1, dup.gold_pieces.size
@@ -81,6 +90,7 @@ class TestDeepCloneable < Test::Unit::TestCase
81
90
 
82
91
  def test_multiple_and_deep_include_association_with_array
83
92
  dup = @jack.send(@@clone_method, :include => [{:treasures => :gold_pieces}, :mateys])
93
+ assert dup.new_record?
84
94
  assert dup.save
85
95
  assert_equal 1, dup.treasures.size
86
96
  assert_equal 1, dup.gold_pieces.size
@@ -89,12 +99,14 @@ class TestDeepCloneable < Test::Unit::TestCase
89
99
 
90
100
  def test_with_belongs_to_relation
91
101
  dup = @jack.send(@@clone_method, :include => :parrot)
102
+ assert dup.new_record?
92
103
  assert dup.save
93
104
  assert_not_equal dup.parrot, @jack.parrot
94
105
  end
95
106
 
96
107
  def test_should_pass_nested_exceptions
97
108
  dup = @jack.send(@@clone_method, :include => :parrot, :except => [:name, { :parrot => [:name] }])
109
+ assert dup.new_record?
98
110
  assert dup.save
99
111
  assert_not_equal dup.parrot, @jack.parrot
100
112
  assert_not_nil @jack.parrot.name
@@ -104,6 +116,7 @@ class TestDeepCloneable < Test::Unit::TestCase
104
116
  def test_should_not_double_dup_when_using_dictionary
105
117
  current_matey_count = Matey.count
106
118
  dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
119
+ assert dup.new_record?
107
120
  dup.save!
108
121
 
109
122
  assert_equal current_matey_count + 1, Matey.count
@@ -116,6 +129,7 @@ class TestDeepCloneable < Test::Unit::TestCase
116
129
  @jack.mateys.each{|m| dict[:mateys][m] = m.send(@@clone_method) }
117
130
 
118
131
  dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :dictionary => dict)
132
+ assert dup.new_record?
119
133
  dup.save!
120
134
 
121
135
  assert_equal current_matey_count + 1, Matey.count
@@ -126,6 +140,7 @@ class TestDeepCloneable < Test::Unit::TestCase
126
140
  @pig = Animal::Pig.create :human => @human, :name => 'big pig'
127
141
 
128
142
  dup_human = @human.send(@@clone_method, :include => [:pigs])
143
+ assert dup_human.new_record?
129
144
  assert dup_human.save
130
145
  assert_equal 1, dup_human.pigs.count
131
146
 
@@ -133,6 +148,7 @@ class TestDeepCloneable < Test::Unit::TestCase
133
148
  @pig2 = @human2.pigs.create :name => 'small pig'
134
149
 
135
150
  dup_human_2 = @human.send(@@clone_method, :include => [:pigs])
151
+ assert dup_human_2.new_record?
136
152
  assert dup_human_2.save
137
153
  assert_equal 1, dup_human_2.pigs.count
138
154
  end
@@ -146,6 +162,7 @@ class TestDeepCloneable < Test::Unit::TestCase
146
162
  @human2.chickens << [@chicken1, @chicken2]
147
163
 
148
164
  dup_human = @human.send(@@clone_method, :include => :ownerships)
165
+ assert dup_human.new_record?
149
166
  assert dup_human.save
150
167
  assert_equal 2, dup_human.chickens.count
151
168
  end
@@ -155,8 +172,34 @@ class TestDeepCloneable < Test::Unit::TestCase
155
172
  kopy.cloned_from_id = original.id
156
173
  end
157
174
 
175
+ assert dup.new_record?
158
176
  assert dup.save
159
177
  assert_equal @jack.id, dup.cloned_from_id
160
178
  assert_equal @jack.parrot.id, dup.parrot.cloned_from_id
161
179
  end
180
+
181
+ def test_should_dup_habtm_associations
182
+ @person1 = Person.create :name => "Bill"
183
+ @person2 = Person.create :name => "Ted"
184
+ @car1 = Car.create :name => 'Mustang'
185
+ @car2 = Car.create :name => 'Camaro'
186
+ @person1.cars << [@car1, @car2]
187
+ @person2.cars << [@car1, @car2]
188
+
189
+ dup_person = @person1.dup :include => :cars
190
+
191
+ assert dup_person.new_record?
192
+ assert_equal [@person1, @person2, dup_person], @car1.people
193
+ assert_equal [@person1, @person2, dup_person], @car2.people
194
+
195
+ assert dup_person.save
196
+
197
+ # did NOT dup the Car instances
198
+ assert_equal 2, Car.all.count
199
+
200
+ # did dup the correct join table rows
201
+ assert_equal @person1.cars, dup_person.cars
202
+ assert_equal 2, dup_person.cars.count
203
+ end
204
+
162
205
  end
data/test/test_helper.rb CHANGED
@@ -7,52 +7,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
7
 
8
8
  require 'active_record'
9
9
  require File.dirname(__FILE__) + '/../init.rb'
10
-
11
- module Animal
12
- class Human < ActiveRecord::Base
13
- has_many :pigs
14
-
15
- has_many :ownerships
16
- has_many :chickens, :through => :ownerships
17
- end
18
- class Pig < ActiveRecord::Base
19
- belongs_to :human
20
- end
21
-
22
- class Chicken < ActiveRecord::Base
23
- has_many :ownerships
24
- has_many :humans, :through => :ownerships
25
- end
26
-
27
- class Ownership < ActiveRecord::Base
28
- belongs_to :human
29
- belongs_to :chicken
30
-
31
- validates_uniqueness_of :chicken_id, :scope => :human_id
32
- end
33
- end
34
-
35
- class GoldPiece < ActiveRecord::Base; belongs_to :treasure end
36
- class Matey < ActiveRecord::Base; belongs_to :pirate end
37
- class Parrot < ActiveRecord::Base; belongs_to :pirate; attr_accessor :cloned_from_id end
38
- class BattleShip < ActiveRecord::Base; has_many :pirates, :as => :ship end
39
-
40
- class Pirate < ActiveRecord::Base
41
- belongs_to :ship, :polymorphic => true
42
-
43
- has_many :mateys
44
- has_many :treasures, :foreign_key => 'owner'
45
- has_many :gold_pieces, :through => :treasures
46
- has_one :parrot
47
-
48
- attr_accessor :cloned_from_id
49
- end
50
-
51
- class Treasure < ActiveRecord::Base
52
- belongs_to :pirate, :foreign_key => :owner
53
- belongs_to :matey
54
- has_many :gold_pieces
55
- end
10
+ require 'models'
56
11
 
57
12
  def load_schema
58
13
  config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deep_cloneable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-02 00:00:00.000000000 Z
12
+ date: 2012-07-23 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: deep_cloneable
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
14
  - !ruby/object:Gem::Dependency
31
15
  name: rails
32
16
  requirement: !ruby/object:Gem::Requirement
@@ -51,7 +35,7 @@ dependencies:
51
35
  - - ! '>='
52
36
  - !ruby/object:Gem::Version
53
37
  version: '0'
54
- type: :runtime
38
+ type: :development
55
39
  prerelease: false
56
40
  version_requirements: !ruby/object:Gem::Requirement
57
41
  none: false
@@ -79,6 +63,7 @@ files:
79
63
  - init.rb
80
64
  - lib/deep_cloneable.rb
81
65
  - test/database.yml
66
+ - test/models.rb
82
67
  - test/schema.rb
83
68
  - test/test_deep_cloneable.rb
84
69
  - test/test_helper.rb
@@ -96,7 +81,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
81
  version: '0'
97
82
  segments:
98
83
  - 0
99
- hash: -1579513982850858765
84
+ hash: -3012807303620209218
100
85
  required_rubygems_version: !ruby/object:Gem::Requirement
101
86
  none: false
102
87
  requirements: