deep_cloneable 1.5.1 → 1.5.2

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/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+
7
+ gemfile:
8
+ - gemfiles/3.0.gemfile
9
+ - gemfiles/3.1.gemfile
10
+ - gemfiles/3.2.gemfile
data/Appraisals ADDED
@@ -0,0 +1,11 @@
1
+ appraise '3.0' do
2
+ gem 'activerecord', '~> 3.0'
3
+ end
4
+
5
+ appraise '3.1' do
6
+ gem 'activerecord', '~> 3.1'
7
+ end
8
+
9
+ appraise '3.2' do
10
+ gem 'activerecord', '~> 3.2'
11
+ end
data/Gemfile CHANGED
@@ -1,11 +1,8 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'activerecord', '>= 3.1'
3
+ gem 'appraisal'
4
+ gem 'activerecord', '>= 3.2'
5
+ gem 'jeweler'
6
+ gem 'sqlite3'
4
7
 
5
- group :development do
6
- gem 'jeweler'
7
- end
8
-
9
- group :test do
10
- gem 'sqlite3'
11
- end
8
+ # gem 'debugger'
data/Gemfile.lock CHANGED
@@ -1,38 +1,42 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activemodel (3.2.12)
5
- activesupport (= 3.2.12)
4
+ activemodel (3.2.13)
5
+ activesupport (= 3.2.13)
6
6
  builder (~> 3.0.0)
7
- activerecord (3.2.12)
8
- activemodel (= 3.2.12)
9
- activesupport (= 3.2.12)
7
+ activerecord (3.2.13)
8
+ activemodel (= 3.2.13)
9
+ activesupport (= 3.2.13)
10
10
  arel (~> 3.0.2)
11
11
  tzinfo (~> 0.3.29)
12
- activesupport (3.2.12)
13
- i18n (~> 0.6)
12
+ activesupport (3.2.13)
13
+ i18n (= 0.6.1)
14
14
  multi_json (~> 1.0)
15
+ appraisal (0.5.2)
16
+ bundler
17
+ rake
15
18
  arel (3.0.2)
16
19
  builder (3.0.4)
17
20
  git (1.2.5)
18
- i18n (0.6.4)
21
+ i18n (0.6.1)
19
22
  jeweler (1.8.4)
20
23
  bundler (~> 1.0)
21
24
  git (>= 1.2.5)
22
25
  rake
23
26
  rdoc
24
- json (1.7.7)
25
- multi_json (1.6.1)
26
- rake (10.0.3)
27
- rdoc (4.0.0)
27
+ json (1.8.0)
28
+ multi_json (1.7.3)
29
+ rake (10.0.4)
30
+ rdoc (4.0.1)
28
31
  json (~> 1.4)
29
32
  sqlite3 (1.3.7)
30
- tzinfo (0.3.36)
33
+ tzinfo (0.3.37)
31
34
 
32
35
  PLATFORMS
33
36
  ruby
34
37
 
35
38
  DEPENDENCIES
36
- activerecord (>= 3.1)
39
+ activerecord (>= 3.2)
40
+ appraisal
37
41
  jeweler
38
42
  sqlite3
data/README.rdoc CHANGED
@@ -1,12 +1,14 @@
1
1
  = Deep_cloneable
2
2
 
3
+ {<img src="https://travis-ci.org/moiristo/deep_cloneable.png?branch=master" alt="Build Status" />}[https://travis-ci.org/moiristo/deep_cloneable]
4
+
3
5
  This gem gives every ActiveRecord::Base object the possibility to do a deep clone. It is a rails3 upgrade of the deep_cloning plugin (http://github.com/openminds/deep_cloning).
4
6
 
5
7
  == Requirements
6
8
 
7
- * Ruby 1.8.7, 1.9, 2.0.0
9
+ * Ruby 1.8.7, 1.9.3, 2.0.0
8
10
 
9
- * Activerecord 3.1, 3.2
11
+ * Activerecord 3.0 (when using _dup_), 3.1, 3.2
10
12
 
11
13
  * Rails 2.x/3.0 users, please check out the 'rails2.x-3.0' branch.
12
14
 
@@ -14,7 +16,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
14
16
 
15
17
  * In your Gemfile:
16
18
 
17
- gem 'deep_cloneable', '~> 1.5.0'
19
+ gem 'deep_cloneable', '~> 1.5.2'
18
20
 
19
21
  == Example
20
22
 
@@ -71,6 +73,8 @@ If this is not an option for you, it is also possible to populate the dictionary
71
73
  * fractious
72
74
  * Georges Gabereau
73
75
  * Christophe Belpaire
76
+ * Kevin Carter
77
+ * fokcep
74
78
 
75
79
  == Note on Patches/Pull Requests
76
80
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
- require 'rake'
2
+ require 'bundler/setup'
3
+ require 'appraisal'
3
4
 
4
5
  begin
5
6
  require 'jeweler'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.1
1
+ 1.5.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "deep_cloneable"
8
- s.version = "1.5.1"
8
+ s.version = "1.5.2"
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 = "2013-03-06"
12
+ s.date = "2013-06-10"
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 = [
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
+ ".travis.yml",
22
+ "Appraisals",
21
23
  "Gemfile",
22
24
  "Gemfile.lock",
23
25
  "LICENSE",
@@ -25,6 +27,12 @@ Gem::Specification.new do |s|
25
27
  "Rakefile",
26
28
  "VERSION",
27
29
  "deep_cloneable.gemspec",
30
+ "gemfiles/3.0.gemfile",
31
+ "gemfiles/3.0.gemfile.lock",
32
+ "gemfiles/3.1.gemfile",
33
+ "gemfiles/3.1.gemfile.lock",
34
+ "gemfiles/3.2.gemfile",
35
+ "gemfiles/3.2.gemfile.lock",
28
36
  "init.rb",
29
37
  "lib/deep_cloneable.rb",
30
38
  "test/database.yml",
@@ -35,22 +43,28 @@ Gem::Specification.new do |s|
35
43
  ]
36
44
  s.homepage = "http://github.com/moiristo/deep_cloneable"
37
45
  s.require_paths = ["lib"]
38
- s.rubygems_version = "1.8.24"
46
+ s.rubygems_version = "1.8.25"
39
47
  s.summary = "This gem gives every ActiveRecord::Base object the possibility to do a deep clone."
40
48
 
41
49
  if s.respond_to? :specification_version then
42
50
  s.specification_version = 3
43
51
 
44
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
- s.add_runtime_dependency(%q<activerecord>, [">= 3.1"])
46
- s.add_development_dependency(%q<jeweler>, [">= 0"])
53
+ s.add_runtime_dependency(%q<appraisal>, [">= 0"])
54
+ s.add_runtime_dependency(%q<activerecord>, [">= 3.2"])
55
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
56
+ s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
47
57
  else
48
- s.add_dependency(%q<activerecord>, [">= 3.1"])
58
+ s.add_dependency(%q<appraisal>, [">= 0"])
59
+ s.add_dependency(%q<activerecord>, [">= 3.2"])
49
60
  s.add_dependency(%q<jeweler>, [">= 0"])
61
+ s.add_dependency(%q<sqlite3>, [">= 0"])
50
62
  end
51
63
  else
52
- s.add_dependency(%q<activerecord>, [">= 3.1"])
64
+ s.add_dependency(%q<appraisal>, [">= 0"])
65
+ s.add_dependency(%q<activerecord>, [">= 3.2"])
53
66
  s.add_dependency(%q<jeweler>, [">= 0"])
67
+ s.add_dependency(%q<sqlite3>, [">= 0"])
54
68
  end
55
69
  end
56
70
 
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "jeweler"
7
+ gem "sqlite3"
8
+ gem "activerecord", "~> 3.0"
9
+
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.13)
5
+ activesupport (= 3.2.13)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.13)
8
+ activemodel (= 3.2.13)
9
+ activesupport (= 3.2.13)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
12
+ activesupport (3.2.13)
13
+ i18n (= 0.6.1)
14
+ multi_json (~> 1.0)
15
+ appraisal (0.5.2)
16
+ bundler
17
+ rake
18
+ arel (3.0.2)
19
+ builder (3.0.4)
20
+ git (1.2.5)
21
+ i18n (0.6.1)
22
+ jeweler (1.8.4)
23
+ bundler (~> 1.0)
24
+ git (>= 1.2.5)
25
+ rake
26
+ rdoc
27
+ json (1.8.0)
28
+ multi_json (1.7.3)
29
+ rake (10.0.4)
30
+ rdoc (4.0.1)
31
+ json (~> 1.4)
32
+ sqlite3 (1.3.7)
33
+ tzinfo (0.3.37)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ activerecord (~> 3.0)
40
+ appraisal
41
+ jeweler
42
+ sqlite3
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "jeweler"
7
+ gem "sqlite3"
8
+ gem "activerecord", "~> 3.1"
9
+
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.13)
5
+ activesupport (= 3.2.13)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.13)
8
+ activemodel (= 3.2.13)
9
+ activesupport (= 3.2.13)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
12
+ activesupport (3.2.13)
13
+ i18n (= 0.6.1)
14
+ multi_json (~> 1.0)
15
+ appraisal (0.5.2)
16
+ bundler
17
+ rake
18
+ arel (3.0.2)
19
+ builder (3.0.4)
20
+ git (1.2.5)
21
+ i18n (0.6.1)
22
+ jeweler (1.8.4)
23
+ bundler (~> 1.0)
24
+ git (>= 1.2.5)
25
+ rake
26
+ rdoc
27
+ json (1.8.0)
28
+ multi_json (1.7.3)
29
+ rake (10.0.4)
30
+ rdoc (4.0.1)
31
+ json (~> 1.4)
32
+ sqlite3 (1.3.7)
33
+ tzinfo (0.3.37)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ activerecord (~> 3.1)
40
+ appraisal
41
+ jeweler
42
+ sqlite3
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "jeweler"
7
+ gem "sqlite3"
8
+ gem "activerecord", "~> 3.2"
9
+
@@ -0,0 +1,42 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.13)
5
+ activesupport (= 3.2.13)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.13)
8
+ activemodel (= 3.2.13)
9
+ activesupport (= 3.2.13)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
12
+ activesupport (3.2.13)
13
+ i18n (= 0.6.1)
14
+ multi_json (~> 1.0)
15
+ appraisal (0.5.2)
16
+ bundler
17
+ rake
18
+ arel (3.0.2)
19
+ builder (3.0.4)
20
+ git (1.2.5)
21
+ i18n (0.6.1)
22
+ jeweler (1.8.4)
23
+ bundler (~> 1.0)
24
+ git (>= 1.2.5)
25
+ rake
26
+ rdoc
27
+ json (1.8.0)
28
+ multi_json (1.7.3)
29
+ rake (10.0.4)
30
+ rdoc (4.0.1)
31
+ json (~> 1.4)
32
+ sqlite3 (1.3.7)
33
+ tzinfo (0.3.37)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ activerecord (~> 3.2)
40
+ appraisal
41
+ jeweler
42
+ sqlite3
@@ -3,12 +3,12 @@ class ActiveRecord::Base
3
3
  # ActiveRecord::Base has its own dup method for Ruby 1.8.7. We have to
4
4
  # redefine it and put it in a module so that we can override it in a
5
5
  # module and call the original with super().
6
- if !Object.respond_to? :initialize_dup, true
6
+ unless Object.respond_to?(:initialize_dup, true)
7
7
  ActiveRecord::Base.class_eval do
8
8
  module Dup
9
9
  def dup
10
10
  copy = super
11
- copy.initialize_dup(self)
11
+ copy.send(:initialize_dup, self)
12
12
  copy
13
13
  end
14
14
  end
@@ -57,7 +57,7 @@ class ActiveRecord::Base
57
57
  # ==== Cloning a model without an attribute or nested multiple attributes
58
58
  # pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
59
59
  #
60
- define_method :dup do |*args, &block|
60
+ def dup *args, &block
61
61
  options = args[0] || {}
62
62
 
63
63
  dict = options[:dictionary]
@@ -89,9 +89,9 @@ class ActiveRecord::Base
89
89
  association = association.keys.first
90
90
  end
91
91
 
92
- opts = deep_associations.blank? ? {} : {:include => deep_associations}
93
- opts.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
94
- opts.merge!(:dictionary => dict) if dict
92
+ dup_options = deep_associations.blank? ? {} : {:include => deep_associations}
93
+ dup_options.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
94
+ dup_options.merge!(:dictionary => dict) if dict
95
95
 
96
96
  association_reflection = self.class.reflect_on_association(association)
97
97
  raise AssociationNotFoundException.new("#{self.class}##{association}") if association_reflection.nil?
@@ -106,34 +106,11 @@ class ActiveRecord::Base
106
106
  end
107
107
  end
108
108
 
109
- cloned_object = case association_reflection.macro
110
- when :belongs_to, :has_one
111
- self.send(association) && self.send(association).send(__method__, opts, &block)
112
- when :has_many
113
- primary_key_name = association_reflection.foreign_key.to_s
114
-
115
- reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
116
- a.foreign_key.to_s == primary_key_name
117
- end.try(:name)
118
-
119
- self.send(association).collect do |obj|
120
- tmp = obj.send(__method__, opts, &block)
121
- tmp.send("#{primary_key_name}=", nil)
122
- tmp.send("#{reverse_association_name.to_s}=", kopy) if reverse_association_name
123
- tmp
124
- end
125
- when :has_and_belongs_to_many
126
- primary_key_name = association_reflection.foreign_key.to_s
127
-
128
- reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
129
- (a.macro == :has_and_belongs_to_many) && (a.association_foreign_key.to_s == primary_key_name)
130
- end.try(:name)
131
-
132
- self.send(association).collect do |obj|
133
- obj.send(reverse_association_name).target << kopy
134
- obj
135
- end
136
- end
109
+ cloned_object = send(
110
+ "dup_#{association_reflection.macro}_#{association_reflection.class.name.demodulize.underscore.gsub('_reflection', '')}",
111
+ { :reflection => association_reflection, :association => association, :copy => kopy, :dup_options => dup_options },
112
+ &block
113
+ )
137
114
 
138
115
  kopy.send("#{association}=", cloned_object)
139
116
  end
@@ -141,7 +118,55 @@ class ActiveRecord::Base
141
118
 
142
119
  return kopy
143
120
  end
144
-
121
+
122
+ private
123
+
124
+ def dup_belongs_to_association options, &block
125
+ self.send(options[:association]) && self.send(options[:association]).dup(options[:dup_options], &block)
126
+ end
127
+
128
+ def dup_has_one_association options, &block
129
+ dup_belongs_to_association options, &block
130
+ end
131
+
132
+ def dup_has_many_association options, &block
133
+ primary_key_name = options[:reflection].foreign_key.to_s
134
+
135
+ reverse_association_name = options[:reflection].klass.reflect_on_all_associations.detect do |reflection|
136
+ reflection.foreign_key.to_s == primary_key_name && reflection != options[:reflection]
137
+ end.try(:name)
138
+
139
+ self.send(options[:association]).collect do |obj|
140
+ tmp = obj.dup(options[:dup_options], &block)
141
+ tmp.send("#{primary_key_name}=", nil)
142
+ tmp.send("#{reverse_association_name.to_s}=", options[:copy]) if reverse_association_name
143
+ tmp
144
+ end
145
+ end
146
+
147
+ def dup_has_many_through options, &block
148
+ dup_join_association(
149
+ options.merge(:macro => :has_many, :primary_key_name => options[:reflection].through_reflection.foreign_key.to_s),
150
+ &block)
151
+ end
152
+
153
+ def dup_has_and_belongs_to_many_association options, &block
154
+ dup_join_association(
155
+ options.merge(:macro => :has_and_belongs_to_many, :primary_key_name => options[:reflection].foreign_key.to_s),
156
+ &block)
157
+ end
158
+
159
+ def dup_join_association options, &block
160
+ reverse_association_name = options[:reflection].klass.reflect_on_all_associations.detect do |reflection|
161
+ (reflection.macro == options[:macro]) && (reflection.association_foreign_key.to_s == options[:primary_key_name])
162
+ end.try(:name)
163
+
164
+ self.send(options[:association]).collect do |obj|
165
+ obj.send(reverse_association_name).target << options[:copy]
166
+ obj
167
+ end
168
+ end
169
+
145
170
  class AssociationNotFoundException < StandardError; end
146
171
  end
147
172
 
data/test/models.rb CHANGED
@@ -62,3 +62,23 @@ class ParentWithValidation < ActiveRecord::Base
62
62
  has_many :children, :class_name => 'ChildWithValidation'
63
63
  validates :name, :presence => true
64
64
  end
65
+
66
+ class Part < ActiveRecord::Base
67
+ # belongs_to :parent_part, :class_name => 'Part'
68
+ has_many :child_parts, :class_name => 'Part', :foreign_key => 'parent_part_id'
69
+ end
70
+
71
+ class Student < ActiveRecord::Base
72
+ has_many :student_assignments, :dependent => :destroy
73
+ has_many :subjects, :through => :student_assignments
74
+ end
75
+
76
+ class Subject < ActiveRecord::Base
77
+ has_many :student_assignments, :dependent => :destroy
78
+ has_many :students, :through => :student_assignments
79
+ end
80
+
81
+ class StudentAssignment < ActiveRecord::Base
82
+ belongs_to :subject
83
+ belongs_to :student
84
+ end
data/test/schema.rb CHANGED
@@ -71,4 +71,21 @@ ActiveRecord::Schema.define(:version => 1) do
71
71
  t.column :parent_with_validation_id, :integer
72
72
  end
73
73
 
74
+ create_table :parts, :force => true do |t|
75
+ t.column :name, :string
76
+ t.column :parent_part_id, :integer
77
+ end
78
+
79
+ create_table :students, :force => true do |t|
80
+ t.column :name, :string
81
+ end
82
+
83
+ create_table :subjects, :force => true do |t|
84
+ t.column :name, :string
85
+ end
86
+
87
+ create_table :student_assignments, :force => true do |t|
88
+ t.column :student_id, :integer
89
+ t.column :subject_id, :integer
90
+ end
74
91
  end
@@ -3,8 +3,6 @@ require File.dirname(__FILE__) + '/test_helper'
3
3
  class TestDeepCloneable < Test::Unit::TestCase
4
4
  load_schema
5
5
 
6
- @@clone_method = ActiveRecord::VERSION::MAJOR >= 3 && ActiveRecord::VERSION::MINOR > 0 ? :dup : :clone
7
-
8
6
  def setup
9
7
  @jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
10
8
  @polly = Parrot.create(:name => 'Polly', :pirate => @jack)
@@ -15,16 +13,16 @@ class TestDeepCloneable < Test::Unit::TestCase
15
13
  end
16
14
 
17
15
  def test_single_dup_exception
18
- dup = @jack.send(@@clone_method, :except => :name)
16
+ dup = @jack.dup(:except => :name)
19
17
  assert dup.new_record?
20
18
  assert dup.save
21
- assert_equal @jack.name, @jack.send(@@clone_method).name # Old behaviour
19
+ assert_equal @jack.name, @jack.dup.name
22
20
  assert_nil dup.name
23
21
  assert_equal @jack.nick_name, dup.nick_name
24
22
  end
25
23
 
26
24
  def test_multiple_dup_exception
27
- dup = @jack.send(@@clone_method, :except => [:name, :nick_name])
25
+ dup = @jack.dup(:except => [:name, :nick_name])
28
26
  assert dup.new_record?
29
27
  assert dup.save
30
28
  assert_nil dup.name
@@ -33,14 +31,14 @@ class TestDeepCloneable < Test::Unit::TestCase
33
31
  end
34
32
 
35
33
  def test_single_include_association
36
- dup = @jack.send(@@clone_method, :include => :mateys)
34
+ dup = @jack.dup(:include => :mateys)
37
35
  assert dup.new_record?
38
36
  assert dup.save
39
37
  assert_equal 1, dup.mateys.size
40
38
  end
41
39
 
42
40
  def test_single_include_belongs_to_polymorphic_association
43
- dup = @jack.send(@@clone_method, :include => :ship)
41
+ dup = @jack.dup(:include => :ship)
44
42
  assert dup.new_record?
45
43
  assert dup.save
46
44
  assert_not_nil dup.ship
@@ -48,14 +46,14 @@ class TestDeepCloneable < Test::Unit::TestCase
48
46
  end
49
47
 
50
48
  def test_single_include_has_many_polymorphic_association
51
- dup = @ship.send(@@clone_method, :include => :pirates)
49
+ dup = @ship.dup(:include => :pirates)
52
50
  assert dup.new_record?
53
51
  assert dup.save
54
52
  assert dup.pirates.any?
55
53
  end
56
54
 
57
55
  def test_multiple_include_association
58
- dup = @jack.send(@@clone_method, :include => [:mateys, :treasures])
56
+ dup = @jack.dup(:include => [:mateys, :treasures])
59
57
  assert dup.new_record?
60
58
  assert dup.save
61
59
  assert_equal 1, dup.mateys.size
@@ -63,7 +61,7 @@ class TestDeepCloneable < Test::Unit::TestCase
63
61
  end
64
62
 
65
63
  def test_deep_include_association
66
- dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces})
64
+ dup = @jack.dup(:include => {:treasures => :gold_pieces})
67
65
  assert dup.new_record?
68
66
  assert dup.save
69
67
  assert_equal 1, dup.treasures.size
@@ -71,7 +69,7 @@ class TestDeepCloneable < Test::Unit::TestCase
71
69
  end
72
70
 
73
71
  def test_include_association_assignments
74
- dup = @jack.send(@@clone_method, :include => :treasures)
72
+ dup = @jack.dup(:include => :treasures)
75
73
  assert dup.new_record?
76
74
 
77
75
  dup.treasures.each do |treasure|
@@ -80,7 +78,7 @@ class TestDeepCloneable < Test::Unit::TestCase
80
78
  end
81
79
 
82
80
  def test_multiple_and_deep_include_association
83
- dup = @jack.send(@@clone_method, :include => {:treasures => :gold_pieces, :mateys => {}})
81
+ dup = @jack.dup(:include => {:treasures => :gold_pieces, :mateys => {}})
84
82
  assert dup.new_record?
85
83
  assert dup.save
86
84
  assert_equal 1, dup.treasures.size
@@ -89,7 +87,7 @@ class TestDeepCloneable < Test::Unit::TestCase
89
87
  end
90
88
 
91
89
  def test_multiple_and_deep_include_association_with_array
92
- dup = @jack.send(@@clone_method, :include => [{:treasures => :gold_pieces}, :mateys])
90
+ dup = @jack.dup(:include => [{:treasures => :gold_pieces}, :mateys])
93
91
  assert dup.new_record?
94
92
  assert dup.save
95
93
  assert_equal 1, dup.treasures.size
@@ -98,14 +96,14 @@ class TestDeepCloneable < Test::Unit::TestCase
98
96
  end
99
97
 
100
98
  def test_with_belongs_to_relation
101
- dup = @jack.send(@@clone_method, :include => :parrot)
99
+ dup = @jack.dup(:include => :parrot)
102
100
  assert dup.new_record?
103
101
  assert dup.save
104
102
  assert_not_equal dup.parrot, @jack.parrot
105
103
  end
106
104
 
107
105
  def test_should_pass_nested_exceptions
108
- dup = @jack.send(@@clone_method, :include => :parrot, :except => [:name, { :parrot => [:name] }])
106
+ dup = @jack.dup(:include => :parrot, :except => [:name, { :parrot => [:name] }])
109
107
  assert dup.new_record?
110
108
  assert dup.save
111
109
  assert_not_equal dup.parrot, @jack.parrot
@@ -115,7 +113,7 @@ class TestDeepCloneable < Test::Unit::TestCase
115
113
 
116
114
  def test_should_not_double_dup_when_using_dictionary
117
115
  current_matey_count = Matey.count
118
- dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
116
+ dup = @jack.dup(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
119
117
  assert dup.new_record?
120
118
  dup.save!
121
119
 
@@ -126,9 +124,9 @@ class TestDeepCloneable < Test::Unit::TestCase
126
124
  current_matey_count = Matey.count
127
125
 
128
126
  dict = { :mateys => {} }
129
- @jack.mateys.each{|m| dict[:mateys][m] = m.send(@@clone_method) }
127
+ @jack.mateys.each{|m| dict[:mateys][m] = m.dup }
130
128
 
131
- dup = @jack.send(@@clone_method, :include => [:mateys, { :treasures => :matey }], :dictionary => dict)
129
+ dup = @jack.dup(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
132
130
  assert dup.new_record?
133
131
  dup.save!
134
132
 
@@ -139,7 +137,7 @@ class TestDeepCloneable < Test::Unit::TestCase
139
137
  @human = Animal::Human.create :name => "Michael"
140
138
  @pig = Animal::Pig.create :human => @human, :name => 'big pig'
141
139
 
142
- dup_human = @human.send(@@clone_method, :include => [:pigs])
140
+ dup_human = @human.dup(:include => [:pigs])
143
141
  assert dup_human.new_record?
144
142
  assert dup_human.save
145
143
  assert_equal 1, dup_human.pigs.count
@@ -147,7 +145,7 @@ class TestDeepCloneable < Test::Unit::TestCase
147
145
  @human2 = Animal::Human.create :name => "John"
148
146
  @pig2 = @human2.pigs.create :name => 'small pig'
149
147
 
150
- dup_human_2 = @human.send(@@clone_method, :include => [:pigs])
148
+ dup_human_2 = @human.dup(:include => [:pigs])
151
149
  assert dup_human_2.new_record?
152
150
  assert dup_human_2.save
153
151
  assert_equal 1, dup_human_2.pigs.count
@@ -161,14 +159,14 @@ class TestDeepCloneable < Test::Unit::TestCase
161
159
  @human.chickens << [@chicken1, @chicken2]
162
160
  @human2.chickens << [@chicken1, @chicken2]
163
161
 
164
- dup_human = @human.send(@@clone_method, :include => :ownerships)
162
+ dup_human = @human.dup(:include => :ownerships)
165
163
  assert dup_human.new_record?
166
164
  assert dup_human.save
167
165
  assert_equal 2, dup_human.chickens.count
168
166
  end
169
167
 
170
168
  def test_should_dup_with_block
171
- dup = @jack.send(@@clone_method, :include => :parrot) do |original, kopy|
169
+ dup = @jack.dup(:include => :parrot) do |original, kopy|
172
170
  kopy.cloned_from_id = original.id
173
171
  end
174
172
 
@@ -258,4 +256,24 @@ class TestDeepCloneable < Test::Unit::TestCase
258
256
  assert_equal dup_parent.errors.messages, :children => ["is invalid"]
259
257
  end
260
258
 
259
+ def test_self_join_has_many
260
+ parent_part = Part.create(:name => 'Parent')
261
+ child1 = Part.create(:name => 'Child 1', :parent_part_id => parent_part.id)
262
+ child2 = Part.create(:name => 'Child 2', :parent_part_id => parent_part.id)
263
+
264
+ dup_part = parent_part.dup :include => :child_parts
265
+ assert dup_part.save
266
+ assert_equal 2, dup_part.child_parts.size
267
+ end
268
+
269
+ def test_should_include_has_many_through_associations
270
+ subject1 = Subject.create(:name => 'subject 1')
271
+ subject2 = Subject.create(:name => 'subject 2')
272
+ student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
273
+
274
+ dup = student.dup :include => :subjects
275
+ assert_equal 2, dup.subjects.size
276
+ assert_equal [[student, dup],[student, dup]], dup.subjects.map{|subject| subject.students }
277
+ end
278
+
261
279
  end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'pp'
4
+ # require 'debugger'
4
5
 
5
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
7
  $LOAD_PATH.unshift(File.dirname(__FILE__))
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.5.1
4
+ version: 1.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-06 00:00:00.000000000 Z
12
+ date: 2013-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: appraisal
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'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: activerecord
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -18,7 +34,7 @@ dependencies:
18
34
  requirements:
19
35
  - - ! '>='
20
36
  - !ruby/object:Gem::Version
21
- version: '3.1'
37
+ version: '3.2'
22
38
  type: :runtime
23
39
  prerelease: false
24
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +42,7 @@ dependencies:
26
42
  requirements:
27
43
  - - ! '>='
28
44
  - !ruby/object:Gem::Version
29
- version: '3.1'
45
+ version: '3.2'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: jeweler
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -35,7 +51,23 @@ dependencies:
35
51
  - - ! '>='
36
52
  - !ruby/object:Gem::Version
37
53
  version: '0'
38
- type: :development
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: sqlite3
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
39
71
  prerelease: false
40
72
  version_requirements: !ruby/object:Gem::Requirement
41
73
  none: false
@@ -53,6 +85,8 @@ extra_rdoc_files:
53
85
  - README.rdoc
54
86
  files:
55
87
  - .document
88
+ - .travis.yml
89
+ - Appraisals
56
90
  - Gemfile
57
91
  - Gemfile.lock
58
92
  - LICENSE
@@ -60,6 +94,12 @@ files:
60
94
  - Rakefile
61
95
  - VERSION
62
96
  - deep_cloneable.gemspec
97
+ - gemfiles/3.0.gemfile
98
+ - gemfiles/3.0.gemfile.lock
99
+ - gemfiles/3.1.gemfile
100
+ - gemfiles/3.1.gemfile.lock
101
+ - gemfiles/3.2.gemfile
102
+ - gemfiles/3.2.gemfile.lock
63
103
  - init.rb
64
104
  - lib/deep_cloneable.rb
65
105
  - test/database.yml
@@ -81,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
121
  version: '0'
82
122
  segments:
83
123
  - 0
84
- hash: 250465939979745511
124
+ hash: -3147244194353225191
85
125
  required_rubygems_version: !ruby/object:Gem::Requirement
86
126
  none: false
87
127
  requirements:
@@ -90,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
130
  version: '0'
91
131
  requirements: []
92
132
  rubyforge_project:
93
- rubygems_version: 1.8.24
133
+ rubygems_version: 1.8.25
94
134
  signing_key:
95
135
  specification_version: 3
96
136
  summary: This gem gives every ActiveRecord::Base object the possibility to do a deep