deferring 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +16 -15
- data/Appraisals +8 -8
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/deferring.gemspec +1 -1
- data/gemfiles/rails_40.gemfile +1 -1
- data/gemfiles/rails_40.gemfile.lock +34 -30
- data/gemfiles/rails_41.gemfile +1 -1
- data/gemfiles/rails_41.gemfile.lock +35 -31
- data/gemfiles/{rails_30.gemfile → rails_42.gemfile} +1 -1
- data/gemfiles/rails_42.gemfile.lock +64 -0
- data/gemfiles/{rails_32.gemfile → rails_50.gemfile} +1 -1
- data/gemfiles/rails_50.gemfile.lock +63 -0
- data/lib/deferring.rb +55 -52
- data/lib/deferring/deferred_association.rb +8 -6
- data/lib/deferring/deferred_callback_listener.rb +9 -3
- data/lib/deferring/version.rb +1 -3
- data/spec/lib/deferring_habtm_spec.rb +140 -90
- data/spec/lib/deferring_has_many_spec.rb +58 -44
- data/spec/spec_helper.rb +12 -1
- data/spec/support/active_record.rb +5 -5
- metadata +10 -11
- data/gemfiles/rails_30.gemfile.lock +0 -55
- data/gemfiles/rails_32.gemfile.lock +0 -57
- data/spec/support/rails_versions.rb +0 -13
@@ -63,6 +63,33 @@ RSpec.describe 'deferred has_many associations' do
|
|
63
63
|
expect(bob.issues).to be_empty
|
64
64
|
end
|
65
65
|
|
66
|
+
describe '#changed_for_autosave?' do
|
67
|
+
it 'returns true if there is a pending create' do
|
68
|
+
bob.issues = [printer_issue]
|
69
|
+
changed, queries = catch_queries { bob.changed_for_autosave? }
|
70
|
+
expect(queries).to be_empty
|
71
|
+
expect(changed).to eq(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns true if there is a pending delete' do
|
75
|
+
bob.issues = [printer_issue]
|
76
|
+
bob.save!
|
77
|
+
|
78
|
+
bob = Person.where(name: 'Bob').first
|
79
|
+
bob.issues.delete(printer_issue)
|
80
|
+
changed, queries = catch_queries { bob.changed_for_autosave? }
|
81
|
+
expect(queries).to be_empty
|
82
|
+
expect(changed).to eq(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'does not perform any queries if the original association has not been loaded' do
|
86
|
+
bob.issues = [printer_issue]
|
87
|
+
changed, queries = catch_queries { bob.changed_for_autosave? }
|
88
|
+
expect(queries).to be_empty
|
89
|
+
expect(changed).to eq(true)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
66
93
|
describe 'validations' do
|
67
94
|
xit 'does not create a link when parent is not valid'
|
68
95
|
|
@@ -120,26 +147,24 @@ RSpec.describe 'deferred has_many associations' do
|
|
120
147
|
expect(bob.non_validated_issues.first.validation_log).to eq([])
|
121
148
|
end
|
122
149
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
expect{ bob.save }.to raise_error
|
142
|
-
end
|
150
|
+
it 'fails when trying to save the parent' do
|
151
|
+
bob.non_validated_issues = [NonValidatedIssue.new]
|
152
|
+
|
153
|
+
# Rails will raise the following error:
|
154
|
+
# - ActiveRecord::RecordNotSaved:
|
155
|
+
# Failed to replace non_validated_issues because one or more of the new records could not be saved.
|
156
|
+
#
|
157
|
+
# This behaviour is different from the default Rails behaviour.
|
158
|
+
# Rails will normally just save the parent and not save the
|
159
|
+
# association.
|
160
|
+
#
|
161
|
+
# Two ways to avoid this error (using the Deferring gem):
|
162
|
+
# - always use validate: true when user input is involved (e.g.
|
163
|
+
# using nested attributes to update the association),
|
164
|
+
# - add validations to the parent to check validness of the
|
165
|
+
# children when a child record can be valid on itself but invalid
|
166
|
+
# when added to the parent
|
167
|
+
expect{ bob.save }.to raise_error(ActiveRecord::RecordNotSaved)
|
143
168
|
end
|
144
169
|
end
|
145
170
|
|
@@ -312,33 +337,22 @@ RSpec.describe 'deferred has_many associations' do
|
|
312
337
|
bob.save!
|
313
338
|
end
|
314
339
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
expect(bob.issues.loaded?).to be_truthy
|
320
|
-
expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
|
321
|
-
end
|
340
|
+
it 'should have loaded the association when pre-loading' do
|
341
|
+
people = Person.preload(:issues)
|
342
|
+
expect(people[1].issues.loaded?).to be_truthy
|
343
|
+
expect(people[1].issue_ids).to eq [printer_issue.id, db_issue.id]
|
322
344
|
end
|
323
345
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
end
|
330
|
-
|
331
|
-
it 'should have loaded the association when eager loading' do
|
332
|
-
people = Person.eager_load(:issues)
|
333
|
-
expect(people[1].issues.loaded?).to be_truthy
|
334
|
-
expect(people[1].issue_ids).to eq [db_issue.id, printer_issue.id]
|
335
|
-
end
|
346
|
+
it 'should have loaded the association when eager loading' do
|
347
|
+
people = Person.eager_load(:issues)
|
348
|
+
expect(people[1].issues.loaded?).to be_truthy
|
349
|
+
expect(people[1].issue_ids).to eq [db_issue.id, printer_issue.id]
|
350
|
+
end
|
336
351
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
end
|
352
|
+
it 'should have loaded the association when joining' do
|
353
|
+
people = Person.includes(:issues).to_a
|
354
|
+
expect(people[1].issues.loaded?).to be_truthy
|
355
|
+
expect(people[1].issue_ids).to eq [printer_issue.id, db_issue.id]
|
342
356
|
end
|
343
357
|
|
344
358
|
it 'should not have loaded the association when using a regular query' do
|
data/spec/spec_helper.rb
CHANGED
@@ -5,7 +5,6 @@ require 'support/models/team'
|
|
5
5
|
require 'support/models/issue'
|
6
6
|
require 'support/models/address'
|
7
7
|
require 'support/models/non_validated_issue'
|
8
|
-
require 'support/rails_versions'
|
9
8
|
|
10
9
|
RSpec.configure do |config|
|
11
10
|
config.disable_monkey_patching!
|
@@ -27,5 +26,17 @@ RSpec.configure do |config|
|
|
27
26
|
raise ActiveRecord::Rollback
|
28
27
|
end
|
29
28
|
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Catch queries executed within the &block
|
32
|
+
def catch_queries(&block)
|
33
|
+
queries = []
|
34
|
+
callback = lambda { |name, start, finish, id, payload|
|
35
|
+
queries << payload[:sql] if payload[:sql] =~ /^SELECT|UPDATE|INSERT/
|
36
|
+
}
|
30
37
|
|
38
|
+
result = ActiveSupport::Notifications.subscribed(callback, 'sql.active_record') do
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
[result, queries]
|
31
42
|
end
|
@@ -6,7 +6,7 @@ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
|
|
6
6
|
ActiveRecord::Schema.define version: 0 do
|
7
7
|
create_table :people do |t|
|
8
8
|
t.string :name
|
9
|
-
t.timestamps
|
9
|
+
t.timestamps null: false
|
10
10
|
end
|
11
11
|
|
12
12
|
create_table :people_teams, id: false do |t|
|
@@ -16,26 +16,26 @@ ActiveRecord::Schema.define version: 0 do
|
|
16
16
|
|
17
17
|
create_table :teams do |t|
|
18
18
|
t.string :name
|
19
|
-
t.timestamps
|
19
|
+
t.timestamps null: false
|
20
20
|
end
|
21
21
|
|
22
22
|
create_table :issues do |t|
|
23
23
|
t.string :subject
|
24
24
|
t.integer :person_id
|
25
|
-
t.timestamps
|
25
|
+
t.timestamps null: false
|
26
26
|
end
|
27
27
|
|
28
28
|
create_table :addresses do |t|
|
29
29
|
t.integer :addressable_id
|
30
30
|
t.string :addressable_type
|
31
31
|
t.string :street
|
32
|
-
t.timestamps
|
32
|
+
t.timestamps null: false
|
33
33
|
end
|
34
34
|
|
35
35
|
create_table :non_validated_issues do |t|
|
36
36
|
t.string :subject
|
37
37
|
t.integer :person_id
|
38
|
-
t.timestamps
|
38
|
+
t.timestamps null: false
|
39
39
|
end
|
40
40
|
end
|
41
41
|
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
|
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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Roestenburg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,14 +111,14 @@ files:
|
|
111
111
|
- README.md
|
112
112
|
- Rakefile
|
113
113
|
- deferring.gemspec
|
114
|
-
- gemfiles/rails_30.gemfile
|
115
|
-
- gemfiles/rails_30.gemfile.lock
|
116
|
-
- gemfiles/rails_32.gemfile
|
117
|
-
- gemfiles/rails_32.gemfile.lock
|
118
114
|
- gemfiles/rails_40.gemfile
|
119
115
|
- gemfiles/rails_40.gemfile.lock
|
120
116
|
- gemfiles/rails_41.gemfile
|
121
117
|
- gemfiles/rails_41.gemfile.lock
|
118
|
+
- gemfiles/rails_42.gemfile
|
119
|
+
- gemfiles/rails_42.gemfile.lock
|
120
|
+
- gemfiles/rails_50.gemfile
|
121
|
+
- gemfiles/rails_50.gemfile.lock
|
122
122
|
- lib/deferring.rb
|
123
123
|
- lib/deferring/deferred_association.rb
|
124
124
|
- lib/deferring/deferred_callback_listener.rb
|
@@ -133,7 +133,6 @@ files:
|
|
133
133
|
- spec/support/models/non_validated_issue.rb
|
134
134
|
- spec/support/models/person.rb
|
135
135
|
- spec/support/models/team.rb
|
136
|
-
- spec/support/rails_versions.rb
|
137
136
|
homepage: http://github.com/robinroestenburg/deferring
|
138
137
|
licenses:
|
139
138
|
- MIT
|
@@ -154,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
153
|
version: '0'
|
155
154
|
requirements: []
|
156
155
|
rubyforge_project:
|
157
|
-
rubygems_version: 2.
|
156
|
+
rubygems_version: 2.5.1
|
158
157
|
signing_key:
|
159
158
|
specification_version: 4
|
160
159
|
summary: Defer saving ActiveRecord associations until parent is saved
|
@@ -169,4 +168,4 @@ test_files:
|
|
169
168
|
- spec/support/models/non_validated_issue.rb
|
170
169
|
- spec/support/models/person.rb
|
171
170
|
- spec/support/models/team.rb
|
172
|
-
|
171
|
+
has_rdoc:
|
@@ -1,55 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ../
|
3
|
-
specs:
|
4
|
-
deferring (0.2.0)
|
5
|
-
activerecord (> 3.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activemodel (3.0.19)
|
11
|
-
activesupport (= 3.0.19)
|
12
|
-
builder (~> 2.1.2)
|
13
|
-
i18n (~> 0.5.0)
|
14
|
-
activerecord (3.0.19)
|
15
|
-
activemodel (= 3.0.19)
|
16
|
-
activesupport (= 3.0.19)
|
17
|
-
arel (~> 2.0.10)
|
18
|
-
tzinfo (~> 0.3.23)
|
19
|
-
activesupport (3.0.19)
|
20
|
-
appraisal (1.0.0)
|
21
|
-
bundler
|
22
|
-
rake
|
23
|
-
thor (>= 0.14.0)
|
24
|
-
arel (2.0.10)
|
25
|
-
builder (2.1.2)
|
26
|
-
diff-lcs (1.2.5)
|
27
|
-
i18n (0.5.4)
|
28
|
-
rake (10.3.2)
|
29
|
-
rspec (3.0.0)
|
30
|
-
rspec-core (~> 3.0.0)
|
31
|
-
rspec-expectations (~> 3.0.0)
|
32
|
-
rspec-mocks (~> 3.0.0)
|
33
|
-
rspec-core (3.0.0)
|
34
|
-
rspec-support (~> 3.0.0)
|
35
|
-
rspec-expectations (3.0.0)
|
36
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
37
|
-
rspec-support (~> 3.0.0)
|
38
|
-
rspec-mocks (3.0.0)
|
39
|
-
rspec-support (~> 3.0.0)
|
40
|
-
rspec-support (3.0.0)
|
41
|
-
sqlite3 (1.3.9)
|
42
|
-
thor (0.19.1)
|
43
|
-
tzinfo (0.3.39)
|
44
|
-
|
45
|
-
PLATFORMS
|
46
|
-
ruby
|
47
|
-
|
48
|
-
DEPENDENCIES
|
49
|
-
activerecord (= 3.0.19)
|
50
|
-
appraisal
|
51
|
-
bundler (~> 1.3)
|
52
|
-
deferring!
|
53
|
-
rake
|
54
|
-
rspec
|
55
|
-
sqlite3
|
@@ -1,57 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ../
|
3
|
-
specs:
|
4
|
-
deferring (0.2.0)
|
5
|
-
activerecord (> 3.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activemodel (3.2.17)
|
11
|
-
activesupport (= 3.2.17)
|
12
|
-
builder (~> 3.0.0)
|
13
|
-
activerecord (3.2.17)
|
14
|
-
activemodel (= 3.2.17)
|
15
|
-
activesupport (= 3.2.17)
|
16
|
-
arel (~> 3.0.2)
|
17
|
-
tzinfo (~> 0.3.29)
|
18
|
-
activesupport (3.2.17)
|
19
|
-
i18n (~> 0.6, >= 0.6.4)
|
20
|
-
multi_json (~> 1.0)
|
21
|
-
appraisal (1.0.0)
|
22
|
-
bundler
|
23
|
-
rake
|
24
|
-
thor (>= 0.14.0)
|
25
|
-
arel (3.0.3)
|
26
|
-
builder (3.0.4)
|
27
|
-
diff-lcs (1.2.5)
|
28
|
-
i18n (0.6.9)
|
29
|
-
multi_json (1.10.1)
|
30
|
-
rake (10.3.2)
|
31
|
-
rspec (3.0.0)
|
32
|
-
rspec-core (~> 3.0.0)
|
33
|
-
rspec-expectations (~> 3.0.0)
|
34
|
-
rspec-mocks (~> 3.0.0)
|
35
|
-
rspec-core (3.0.0)
|
36
|
-
rspec-support (~> 3.0.0)
|
37
|
-
rspec-expectations (3.0.0)
|
38
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
-
rspec-support (~> 3.0.0)
|
40
|
-
rspec-mocks (3.0.0)
|
41
|
-
rspec-support (~> 3.0.0)
|
42
|
-
rspec-support (3.0.0)
|
43
|
-
sqlite3 (1.3.9)
|
44
|
-
thor (0.19.1)
|
45
|
-
tzinfo (0.3.39)
|
46
|
-
|
47
|
-
PLATFORMS
|
48
|
-
ruby
|
49
|
-
|
50
|
-
DEPENDENCIES
|
51
|
-
activerecord (= 3.2.17)
|
52
|
-
appraisal
|
53
|
-
bundler (~> 1.3)
|
54
|
-
deferring!
|
55
|
-
rake
|
56
|
-
rspec
|
57
|
-
sqlite3
|