deferring 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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