deep_cloneable 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6f91e67baa2dd1118f4ab807655791d72e9f69e
4
- data.tar.gz: 3cd1a98dd2828ab747e267f8f749b8fc41b4cc79
3
+ metadata.gz: 2965ed86adcfda63e876533015e4a55e4fb0316f
4
+ data.tar.gz: 6d9ef9a44e135ecf9baa769e721e25c62b4f893c
5
5
  SHA512:
6
- metadata.gz: 2a23f55f760ec9de1b06fc1f2fe09f4fa28224c0a545e3607b185129c8625e7344a6e3c5de5e400bc2caedf5b39ccaa890a5e5fcddda5cceea47b2b88fad4910
7
- data.tar.gz: 490a16bde06aaa25654aa0264214f5b7474d7233c7681da4acaef0073a45fd1ecbe14814fb1cbbd219b2647b5d4c914f3dee919d33c361dc0cfcb2eeb0a7ace1
6
+ metadata.gz: e11fe1537382bc8fe904aa02f0dd33b205bc926093d383f6ef7a0023509c279e430f04732f5707c62ef077b7de86516f66d935e90055e4fd1b8a1b2f6612bb93
7
+ data.tar.gz: c2b879a4b1885214c647c632ace3f8ba895b0c13ac12d34bed2c2bb9ccf776060a1add719a6a1219a9fbe7c4b3a4b30dcb33149466bda4fefec4b2b3f66c2eb0
@@ -26,43 +26,47 @@ GEM
26
26
  faraday (0.9.2)
27
27
  multipart-post (>= 1.2, < 3)
28
28
  git (1.2.9.1)
29
- github_api (0.14.0)
29
+ github_api (0.16.0)
30
30
  addressable (~> 2.4.0)
31
31
  descendants_tracker (~> 0.0.4)
32
32
  faraday (~> 0.8, < 0.10)
33
33
  hashie (>= 3.4)
34
- oauth2
35
- hashie (3.4.4)
34
+ mime-types (>= 1.16, < 3.0)
35
+ oauth2 (~> 1.0)
36
+ hashie (3.5.5)
36
37
  highline (1.6.21)
37
38
  i18n (0.6.11)
38
- jeweler (2.1.1)
39
+ jeweler (2.3.6)
39
40
  builder
40
- bundler (>= 1.0)
41
+ bundler (>= 1)
41
42
  git (>= 1.2.5)
42
- github_api
43
+ github_api (~> 0.16.0)
43
44
  highline (>= 1.6.15)
44
45
  nokogiri (>= 1.5.10)
46
+ psych (~> 2.2)
45
47
  rake
46
48
  rdoc
47
- semver
49
+ semver2
48
50
  json (1.8.3)
49
- jwt (1.5.1)
51
+ jwt (1.5.6)
52
+ mime-types (2.99.3)
50
53
  minitest (5.9.0)
51
54
  multi_json (1.12.1)
52
- multi_xml (0.5.5)
55
+ multi_xml (0.6.0)
53
56
  multipart-post (2.0.0)
54
57
  nokogiri (1.5.11)
55
- oauth2 (1.1.0)
56
- faraday (>= 0.8, < 0.10)
57
- jwt (~> 1.0, < 1.5.2)
58
+ oauth2 (1.4.0)
59
+ faraday (>= 0.8, < 0.13)
60
+ jwt (~> 1.0)
58
61
  multi_json (~> 1.3)
59
62
  multi_xml (~> 0.5)
60
63
  rack (>= 1.2, < 3)
64
+ psych (2.2.4)
61
65
  rack (1.6.4)
62
66
  rake (10.5.0)
63
67
  rdoc (4.2.2)
64
68
  json (~> 1.4)
65
- semver (1.0.1)
69
+ semver2 (3.4.2)
66
70
  sqlite3 (1.3.11)
67
71
  thor (0.19.1)
68
72
  thread_safe (0.3.5)
@@ -87,4 +91,4 @@ DEPENDENCIES
87
91
  sqlite3
88
92
 
89
93
  BUNDLED WITH
90
- 1.11.2
94
+ 1.14.6
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2016 Reinier de Lange
1
+ Copyright (c) 2017 Reinier de Lange
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.2
1
+ 2.3.0
@@ -2,18 +2,18 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: deep_cloneable 2.2.2 ruby lib
5
+ # stub: deep_cloneable 2.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
- s.name = "deep_cloneable".freeze
9
- s.version = "2.2.2"
8
+ s.name = "deep_cloneable"
9
+ s.version = "2.3.0"
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib".freeze]
13
- s.authors = ["Reinier de Lange".freeze]
14
- s.date = "2016-10-10"
15
- s.description = "Extends the functionality of ActiveRecord::Base#dup to perform a deep clone that includes user specified associations. ".freeze
16
- s.email = "r.j.delange@nedforce.nl".freeze
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Reinier de Lange"]
14
+ s.date = "2017-06-14"
15
+ s.description = "Extends the functionality of ActiveRecord::Base#dup to perform a deep clone that includes user specified associations. "
16
+ s.email = "r.j.delange@nedforce.nl"
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE",
19
19
  "readme.md"
@@ -49,21 +49,21 @@ Gem::Specification.new do |s|
49
49
  "test/test_deep_cloneable.rb",
50
50
  "test/test_helper.rb"
51
51
  ]
52
- s.homepage = "http://github.com/moiristo/deep_cloneable".freeze
53
- s.licenses = ["MIT".freeze]
54
- s.rubygems_version = "2.6.4".freeze
55
- s.summary = "This gem gives every ActiveRecord::Base object the possibility to do a deep clone.".freeze
52
+ s.homepage = "http://github.com/moiristo/deep_cloneable"
53
+ s.licenses = ["MIT"]
54
+ s.rubygems_version = "2.4.8"
55
+ s.summary = "This gem gives every ActiveRecord::Base object the possibility to do a deep clone."
56
56
 
57
57
  if s.respond_to? :specification_version then
58
58
  s.specification_version = 4
59
59
 
60
60
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
- s.add_runtime_dependency(%q<activerecord>.freeze, ["< 5.2.0", ">= 3.1.0"])
61
+ s.add_runtime_dependency(%q<activerecord>, ["< 5.2.0", ">= 3.1.0"])
62
62
  else
63
- s.add_dependency(%q<activerecord>.freeze, ["< 5.2.0", ">= 3.1.0"])
63
+ s.add_dependency(%q<activerecord>, ["< 5.2.0", ">= 3.1.0"])
64
64
  end
65
65
  else
66
- s.add_dependency(%q<activerecord>.freeze, ["< 5.2.0", ">= 3.1.0"])
66
+ s.add_dependency(%q<activerecord>, ["< 5.2.0", ">= 3.1.0"])
67
67
  end
68
68
  end
69
69
 
@@ -39,7 +39,7 @@ class ActiveRecord::Base
39
39
  end
40
40
 
41
41
  if options[:include]
42
- Array(options[:include]).each do |association, conditions_or_deep_associations|
42
+ normalized_includes_list(options[:include]).each do |association, conditions_or_deep_associations|
43
43
  conditions = {}
44
44
 
45
45
  if association.kind_of? Hash
@@ -54,34 +54,37 @@ class ActiveRecord::Base
54
54
  conditions_or_deep_associations.delete_if {|entry| conditions.merge!(entry) if entry.is_a?(Hash) && (entry.key?(:if) || entry.key?(:unless)) }
55
55
  end
56
56
 
57
- dup_options = conditions_or_deep_associations.blank? ? {} : {:include => conditions_or_deep_associations}
57
+ dup_options = {}
58
+ dup_options.merge!(:include => conditions_or_deep_associations) if conditions_or_deep_associations.present?
58
59
  dup_options.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
59
60
  dup_options.merge!(:only => deep_onlinesses[association]) if deep_onlinesses[association]
60
61
  dup_options.merge!(:dictionary => dict) if dict
61
-
62
- association_reflection = self.class.reflect_on_association(association)
63
- raise AssociationNotFoundException.new("#{self.class}##{association}") if association_reflection.nil?
64
-
65
- if options[:validate] == false
66
- kopy.instance_eval do
67
- # Force :validate => false on all saves.
68
- def perform_validations(options={})
69
- options[:validate] = false
70
- super(options)
62
+ dup_options.merge!(:skip_missing_associations => options[:skip_missing_associations]) if options[:skip_missing_associations]
63
+
64
+ if association_reflection = self.class.reflect_on_association(association)
65
+ if options[:validate] == false
66
+ kopy.instance_eval do
67
+ # Force :validate => false on all saves.
68
+ def perform_validations(options={})
69
+ options[:validate] = false
70
+ super(options)
71
+ end
71
72
  end
72
73
  end
73
- end
74
74
 
75
- association_type = association_reflection.macro
76
- association_type = "#{association_type}_through" if association_reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
75
+ association_type = association_reflection.macro
76
+ association_type = "#{association_type}_through" if association_reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
77
77
 
78
- duped_object = send(
79
- "dup_#{association_type}_association",
80
- { :reflection => association_reflection, :association => association, :copy => kopy, :conditions => conditions, :dup_options => dup_options },
81
- &block
82
- )
78
+ duped_object = send(
79
+ "dup_#{association_type}_association",
80
+ { :reflection => association_reflection, :association => association, :copy => kopy, :conditions => conditions, :dup_options => dup_options },
81
+ &block
82
+ )
83
83
 
84
- kopy.send("#{association}=", duped_object)
84
+ kopy.send("#{association}=", duped_object)
85
+ elsif !options[:skip_missing_associations]
86
+ raise AssociationNotFoundException.new("#{self.class}##{association}")
87
+ end
85
88
  end
86
89
  end
87
90
 
@@ -173,6 +176,19 @@ class ActiveRecord::Base
173
176
  def evaluate_conditions object, conditions
174
177
  (conditions[:if] && conditions[:if].call(object)) || (conditions[:unless] && !conditions[:unless].call(object))
175
178
  end
179
+
180
+ def normalized_includes_list includes
181
+ list = []
182
+ Array(includes).each do |item|
183
+ if item.is_a?(Hash) && item.size > 1
184
+ item.each{|key, value| list << { key => value } }
185
+ else
186
+ list << item
187
+ end
188
+ end
189
+
190
+ list
191
+ end
176
192
 
177
193
  class AssociationNotFoundException < StandardError; end
178
194
 
data/readme.md CHANGED
@@ -7,7 +7,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
7
7
  ## Requirements
8
8
 
9
9
  * Ruby 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.5, 2.2.2, 2.3.0 (tested)
10
- * Activerecord 3.1, 3.2, 4.0, 4.1, 4.2, 5.0.0-rc1 (tested)
10
+ * Activerecord 3.1, 3.2, 4.0, 4.1, 4.2, 5.0.0.1 (tested)
11
11
  * Rails 2.x/3.0 users, please check out the 'rails2.x-3.0' branch
12
12
 
13
13
  ## Installation
@@ -15,7 +15,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
15
15
  * Add deep_cloneable to your Gemfile:
16
16
 
17
17
  ```ruby
18
- gem 'deep_cloneable', '~> 2.2.2'
18
+ gem 'deep_cloneable', '~> 2.3.0'
19
19
  ```
20
20
 
21
21
  ## Upgrading from v1
@@ -123,6 +123,14 @@ pirate.deep_clone include: :parrot do |original, kopy|
123
123
  end
124
124
  ```
125
125
 
126
+ ### Skipping missing associations
127
+
128
+ By default, deep_cloneable will throw a `ActiveRecord::Base::DeepCloneable::AssociationNotFoundException` error when an association cannot be found. You can also skip missing associations by specifying `skip_missing_associations` if needed, for example when you have associations on some (but not all) subclasses of an STI model:
129
+
130
+ ```ruby
131
+ pirate.deep_clone include: [:parrot, :rum], skip_missing_associations: true
132
+ ```
133
+
126
134
  ### Note on Patches/Pull Requests
127
135
 
128
136
  * Fork the project.
@@ -135,4 +143,4 @@ end
135
143
 
136
144
  ### Copyright
137
145
 
138
- Copyright &copy; 2016 Reinier de Lange. See LICENSE for details.
146
+ Copyright &copy; 2017 Reinier de Lange. See LICENSE for details.
@@ -5,15 +5,28 @@ module Animal
5
5
  has_many :ownerships
6
6
  has_many :chickens, :through => :ownerships
7
7
  end
8
+
8
9
  class Pig < ActiveRecord::Base
9
10
  belongs_to :human
10
11
  end
11
12
 
12
- class Chicken < ActiveRecord::Base
13
+ class Bird < ActiveRecord::Base
14
+ belongs_to :planet
15
+ end
16
+
17
+ class Chicken < Bird
13
18
  has_many :ownerships
14
19
  has_many :humans, :through => :ownerships
15
20
  end
16
21
 
22
+ class Dove < Bird
23
+ end
24
+
25
+ class Planet < ActiveRecord::Base
26
+ has_many :birds
27
+ end
28
+
29
+
17
30
  class Ownership < ActiveRecord::Base
18
31
  belongs_to :human
19
32
  belongs_to :chicken
@@ -47,10 +47,16 @@ ActiveRecord::Schema.define(:version => 1) do
47
47
  t.column :name, :string
48
48
  end
49
49
 
50
- create_table :chickens, :force => true do |t|
50
+ create_table :planets, :force => true do |t|
51
51
  t.column :name, :string
52
52
  end
53
53
 
54
+ create_table :birds, :force => true do |t|
55
+ t.column :name, :string
56
+ t.column :type, :string
57
+ t.column :planet_id, :integer
58
+ end
59
+
54
60
  create_table :ownerships, :force => true do |t|
55
61
  t.column :human_id, :integer
56
62
  t.column :chicken_id, :integer
@@ -126,6 +126,15 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
126
126
  assert_equal 1, deep_clone.gold_pieces.size
127
127
  assert_equal 1, deep_clone.mateys.size
128
128
  end
129
+
130
+ def test_multiple_and_deep_include_association_with_array_and_multikey_hash
131
+ deep_clone = @jack.deep_clone(:include => [:parrot, {:treasures => :gold_pieces, :mateys => {}}])
132
+ assert deep_clone.new_record?
133
+ assert deep_clone.save
134
+ assert_equal 1, deep_clone.treasures.size
135
+ assert_equal 1, deep_clone.gold_pieces.size
136
+ assert_equal 1, deep_clone.mateys.size
137
+ end
129
138
 
130
139
  def test_with_belongs_to_relation
131
140
  deep_clone = @jack.deep_clone(:include => :parrot)
@@ -208,6 +217,21 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
208
217
  assert_equal 2, deep_clone_human.chickens.count
209
218
  end
210
219
 
220
+ def test_should_skip_missing_associations
221
+ @earth = Animal::Planet.create :name => 'Earth'
222
+ @human = Animal::Human.create :name => "Michael"
223
+ @chicken = Animal::Chicken.create :name => 'Chick', :humans => [@human], :planet => @earth, :humans => [@human]
224
+ @dove = Animal::Dove.create :name => 'Dovey', :planet => @earth
225
+
226
+ assert_raises ActiveRecord::Base::DeepCloneable::AssociationNotFoundException do
227
+ @earth.deep_clone(:include => { :birds => :ownerships })
228
+ end
229
+
230
+ deep_clone_earth = @earth.deep_clone(:include => { :birds => :ownerships }, :skip_missing_associations => true)
231
+ assert_equal 2, deep_clone_earth.birds.size
232
+ assert deep_clone_earth.birds.detect{|bird| bird.is_a?(Animal::Chicken) }.ownerships.any?
233
+ end
234
+
211
235
  def test_should_deep_clone_with_block
212
236
  deep_clone = @jack.deep_clone(:include => :parrot) do |original, kopy|
213
237
  kopy.cloned_from_id = original.id
@@ -427,4 +451,5 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
427
451
  assert_nil deep_clone.name
428
452
  refute deep_clone.name_changed?
429
453
  end
454
+
430
455
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deep_cloneable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.2
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reinier de Lange
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-10 00:00:00.000000000 Z
11
+ date: 2017-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  version: '0'
89
89
  requirements: []
90
90
  rubyforge_project:
91
- rubygems_version: 2.6.4
91
+ rubygems_version: 2.4.8
92
92
  signing_key:
93
93
  specification_version: 4
94
94
  summary: This gem gives every ActiveRecord::Base object the possibility to do a deep