deferring 0.0.6 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MGM5OTgyNTJhMTg3OTAzNjA2MWM4ODAwNWQxYTRiZjk1ZTM0ODQ0ZQ==
4
+ YmQ0ODk2NjQ5MWRkMDI2ZjIzZjEyNzdjNzk1MGIyNmVkOGEwNmNjZQ==
5
5
  data.tar.gz: !binary |-
6
- YWVmMmQzNmQ2N2EzNDlkYjc2M2EyODNjYzUyZThkMGQ3OTJhODI0Yw==
6
+ MmZmOThmYzFkNDkzOTMzZGNhZmFhYmFkZmViOTc5ZmJmMzZmNjFmYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZTIwY2IyYzczZmIyN2QxYjlhZDU0Mjk5ZDk1ZTI0NmVmMWY0ZjVmMWJjMWIz
10
- NjU1NjUzYWJmNDU4M2I2Y2QwZTA2NDUwMWMzM2QxNTZmODc1ZjRhNjdlNDQw
11
- ZjliOTMxMGMxNTkyMzIyODk4ODE4NTY5MzFlNWY0MWM4OGU0Njc=
9
+ OWI3OTAxNjNlNGIzNWZhMGEyMGE5NDM4MzQxODcwMGViZDBmNWNmNDdjZmJl
10
+ ODY0MzVjNTdhNjU4MjU4ZTQwYzBkNzMwNjU3NWQ2YzA4ZDM2OWU2NThlYTMx
11
+ NTAwODZjNzYyNGMzNTQ3ZTUxMjlhMzk2NDg5OTIxZjVlMWM3MWE=
12
12
  data.tar.gz: !binary |-
13
- ODY2MmI3ZDJkZGY3MDg0OWE0NTZkMzNkMDA5MWRkYzY0MTE0OTQyMDAxNzE3
14
- NGEyYjQ2ZDA5OTFmMzIwNzM3MDcyMTVlMTFlZGVkZTJjMDE2ODU4YTY2NmEx
15
- NTU0M2ZiZjAwZjcwNGRlOWQ0MzY1YWM5ZTkxMTQ4NzViMzgwNWQ=
13
+ YTEyYzMyNTJiMzBjOTY1ODkwOGE2OWUzZDRkYzNmMGMyYjAyMTE0N2E0Yjg2
14
+ ZmRjOWNkZjcxZjQxNjQ0Mjc4OGRmMzVjYjYxYjUwYTA5ZmY5OTQzMWQ0Y2Q1
15
+ NWNjNGU4MDk2ZGQ4MTA5YzQ2ZDM2N2EzNTc0MWZlZDI0Yzg2Mjk=
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.5)
4
+ deferring (0.1.0)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.5)
4
+ deferring (0.1.0)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.5)
4
+ deferring (0.1.0)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.5)
4
+ deferring (0.1.0)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
data/lib/deferring.rb CHANGED
@@ -32,12 +32,15 @@ module Deferring
32
32
  end
33
33
 
34
34
  def deferred_accepts_nested_attributes_for(*args)
35
- accepts_nested_attributes_for(*args)
35
+ options = args.extract_options!
36
+ inverse_association_name = options.fetch(:as, self.name.underscore.to_sym)
37
+ accepts_nested_attributes_for(*args, options)
38
+
36
39
  association_name = args.first.to_s
37
40
 
38
41
  # teams_attributes=
39
42
  define_method :"#{association_name}_attributes=" do |records|
40
- find_or_create_deferred_association(association_name, [], nil)
43
+ find_or_create_deferred_association(association_name, [], inverse_association_name)
41
44
 
42
45
  # Remove the records that are to be destroyed from the ids that are to be
43
46
  # assigned to the DeferredAssociation instance.
@@ -110,7 +113,6 @@ module Deferring
110
113
  # the save after the parent object has been saved
111
114
  after_save :"perform_deferred_#{association_name}_save!"
112
115
  define_method :"perform_deferred_#{association_name}_save!" do
113
-
114
116
  find_or_create_deferred_association(association_name, listeners, inverse_association_name)
115
117
 
116
118
  # Send the objects of our delegated association to the original
@@ -80,11 +80,23 @@ module Deferring
80
80
  end
81
81
 
82
82
  def objects=(records)
83
- @objects = records
83
+ @objects = records.map do |record|
84
+ if inverse_name && record.class.reflect_on_association(inverse_name)
85
+ record.send(:"#{inverse_name}=", parent_record)
86
+ end
87
+ record
88
+ end
89
+
84
90
  @original_objects = original_association.to_a.clone
85
91
  objects_loaded!
86
92
 
87
- pending_deletes.each { |record| run_deferring_callbacks(:unlink, record) }
93
+ pending_deletes.each do |record|
94
+ run_deferring_callbacks(:unlink, record) do
95
+ if inverse_name && record.class.reflect_on_association(inverse_name)
96
+ record.send(:"#{inverse_name}=", nil)
97
+ end
98
+ end
99
+ end
88
100
  pending_creates.each { |record| run_deferring_callbacks(:link, record) }
89
101
 
90
102
  @objects
@@ -99,6 +111,10 @@ module Deferring
99
111
  # but it will probably be filtered after saving and retrieving as well.
100
112
  Array(records).flatten.uniq.each do |record|
101
113
  run_deferring_callbacks(:link, record) do
114
+ if inverse_name && record.class.reflect_on_association(inverse_name)
115
+ record.send(:"#{inverse_name}=", parent_record)
116
+ end
117
+
102
118
  objects << record
103
119
  end
104
120
  end
@@ -111,6 +127,10 @@ module Deferring
111
127
  def delete(records)
112
128
  Array(records).flatten.uniq.each do |record|
113
129
  run_deferring_callbacks(:unlink, record) do
130
+ if inverse_name && record.class.reflect_on_association(inverse_name)
131
+ record.send(:"#{inverse_name}=", nil)
132
+ end
133
+
114
134
  objects.delete(record)
115
135
  end
116
136
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Deferring
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.7'
5
5
  end
@@ -11,10 +11,125 @@ RSpec.describe 'deferred has_many associations' do
11
11
  Issue.create!(subject: 'Make me a sandwich!')
12
12
  end
13
13
 
14
+ let(:bob) { Person.where(name: 'Bob').first }
15
+
14
16
  let(:printer_issue) { Issue.where(subject: 'Printer PRT-001 jammed').first }
15
17
  let(:db_issue) { Issue.where(subject: 'Database server DB-1337 down').first }
16
18
  let(:sandwich_issue) { Issue.where(subject: 'Make me a sandwich!').first }
17
19
 
20
+ describe 'deferring' do
21
+ it 'does not create a link until parent is saved' do
22
+ bob.issues << db_issue << printer_issue
23
+ expect{ bob.save! }.to change{ Person.find(bob.id).issues.size }.from(0).to(2)
24
+ end
25
+
26
+ it 'does not unlink until parent is saved' do
27
+ bob.issue_ids = [db_issue.id, printer_issue.id, sandwich_issue.id]
28
+ bob.save!
29
+
30
+ bob.issues.delete([
31
+ Issue.find(db_issue.id),
32
+ Issue.find(sandwich_issue.id)
33
+ ])
34
+
35
+ expect{ bob.save }.to change{ Person.find(bob.id).issues.size }.from(3).to(1)
36
+ end
37
+
38
+ xit 'does not create a link when parent is not valid'
39
+
40
+ it 'replaces existing records when assigning a new set of records' do
41
+ bob.issues = [db_issue]
42
+
43
+ # A mistake was made, Bob wants to submit a printer and a sandwich issue.
44
+ bob.issues = [printer_issue, sandwich_issue]
45
+
46
+ expect{ bob.save }.to change{ Person.find(bob.id).issues.size }.from(0).to(2)
47
+ end
48
+
49
+ it 'sets the belongs_to association of the associated record' do
50
+ bob.issues << printer_issue
51
+ expect(bob.issues.first.person).to eq bob
52
+ end
53
+
54
+ describe '#collection_singular_ids' do
55
+ it 'returns ids of saved & unsaved associated records' do
56
+ bob.issues = [printer_issue, db_issue]
57
+ expect(bob.issue_ids.size).to eq(2)
58
+ expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
59
+
60
+ expect{ bob.save }.to change{ Person.find(bob.id).issue_ids.size }.from(0).to(2)
61
+
62
+ expect(bob.issue_ids.size).to eq(2)
63
+ expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
64
+ end # collection_singular_ids
65
+ end
66
+
67
+ describe '#collections_singular_ids=' do
68
+ it 'sets associated records' do
69
+ bob.issue_ids = [printer_issue.id, db_issue.id]
70
+ bob.save
71
+ expect(bob.issues).to eq [printer_issue, db_issue]
72
+ expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
73
+
74
+ bob.reload
75
+ expect(bob.issues).to eq [printer_issue, db_issue]
76
+ expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
77
+ end
78
+
79
+ it 'replace existing records when assigning a new set of ids of records' do
80
+ bob.issues = [db_issue]
81
+
82
+ bob.issue_ids = [printer_issue.id, sandwich_issue.id]
83
+ expect(bob.issues.length).to eq(2)
84
+
85
+ expect{ bob.save }.to change{ Person.find(bob.id).issues.size }.from(0).to(2)
86
+ end
87
+
88
+ it 'clears empty values from the ids to be assigned' do
89
+ bob.issue_ids = [db_issue.id, '']
90
+ expect(bob.issues.length).to eq(1)
91
+
92
+ expect{ bob.save }.to change{ Person.where(name: 'Bob').first.issues.size }.from(0).to(1)
93
+ end
94
+
95
+ it 'sets the belongs_to association of the associated record' do
96
+ expect(printer_issue.person).to be_nil
97
+ bob.issue_ids = [printer_issue.id]
98
+ expect(bob.issues.first.person).to eq bob
99
+ end
100
+ end # collections_singular_ids=
101
+ end
102
+
103
+ describe 'accepts_nested_attributes' do
104
+ it 'should mass-assign' do
105
+ p = Person.first
106
+ p.issues << printer_issue << db_issue << sandwich_issue
107
+ p.save
108
+
109
+ # Destroy db and sandwich issues. Keep printer issue.
110
+ p = Person.first
111
+ p.attributes = {
112
+ issues_attributes: [
113
+ { id: printer_issue.id },
114
+ { id: sandwich_issue.id, _destroy: true },
115
+ { id: db_issue.id, _destroy: true }
116
+ ]
117
+ }
118
+ expect(p.issues.length).to eq(1)
119
+ expect(p.issue_ids.sort).to eq([1])
120
+
121
+ expect{ p.save! }.to change{ Person.first.issues.size }.from(3).to(1)
122
+ end
123
+
124
+ it 'sets the belongs_to association of the associated record' do
125
+ expect(printer_issue.person).to be_nil
126
+ bob.attributes = {
127
+ issues_attributes: [{ id: printer_issue.id }]
128
+ }
129
+ expect(bob.issues.first.person).to eq bob
130
+ end
131
+ end # accepts_nested_attributes
132
+
18
133
  describe 'preloading associations' do
19
134
  before do
20
135
  bob = Person.where(name: 'Bob').first
@@ -55,10 +170,9 @@ RSpec.describe 'deferred has_many associations' do
55
170
  people = Person.all
56
171
  expect(people[1].issues.loaded?).to be_falsey
57
172
  end
58
- end
173
+ end # preloading associations
59
174
 
60
175
  describe 'active record api' do
61
-
62
176
  describe '#build' do
63
177
  it 'builds a new record' do
64
178
  bob = Person.where(name: 'Bob').first
@@ -74,6 +188,5 @@ RSpec.describe 'deferred has_many associations' do
74
188
  expect(bob.issues.last.person).to eq bob
75
189
  end
76
190
  end
77
- end
78
-
191
+ end # active record api
79
192
  end
@@ -15,6 +15,7 @@ class Person < ActiveRecord::Base
15
15
 
16
16
  deferred_has_many :issues, before_remove: :remove_issue,
17
17
  after_remove: :removed_issue
18
+ deferred_accepts_nested_attributes_for :issues, allow_destroy: true
18
19
 
19
20
  validates_presence_of :name
20
21
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deferring
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robin Roestenburg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-29 00:00:00.000000000 Z
11
+ date: 2014-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord