deferring 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d3b21ec82ca5a7c3f62259abc852c195553ebed1
4
- data.tar.gz: b2a2819985c21278781a1ef8fd1d6b97fef61945
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Mzk2OTEyOGRmMjBkNTIzNzk4MGQ4MmM4ZWE1MmE1MmY4NzliYjEwZQ==
5
+ data.tar.gz: !binary |-
6
+ ZDkyYjNmYWU0OGUxZDFkODkyODhiM2E0MDY3MDgyMDFkYTJiYjlkMw==
5
7
  SHA512:
6
- metadata.gz: 8181bd48cfbef4cc775fcb9a58a24ae60ead0555377fe87551e0629078453d4d55b03e8e7f04cafe3820c4839bfd22cca24dc6cee6921c1e121d5598971aaf81
7
- data.tar.gz: 0b2c33f182e9ce5e2d1b66ecf42cb16abc2f4b92f1bcc5afbbb173f2b8dd919c71876cc66305d3f3d280340351e18993af686c6f5b846f5d3128ac1a1a0d9432
8
+ metadata.gz: !binary |-
9
+ ZjA2OThhM2I1ZTY3MzM5NDA4ZmJlMTQ1YzhmZTQzNmFlZGMzODJmZjc5MjE1
10
+ NzljMzE0YzE0NmE0MzMzNjJjYjM4MTU1MzU0ZTFmNzM1MDZmNWU5MTBiZTEz
11
+ MjExYTlmZWVkZDJlM2I3NTIwNTVkNDNjYWE4YWE4MWY4NjAwZmI=
12
+ data.tar.gz: !binary |-
13
+ YmEwMDNlN2E5ZmVhMGUzODc0YzJmMTAxNWI4MDE5NTNhNDBlNGEyYjFiMzZj
14
+ YzhjM2U4MGFlZjQzYjFkMWJmNDEwMzEzZmJkMTVmZjMzMjhkZmQ0Mzk2OGIz
15
+ OWRhMzk2OTExZjczMjk2NDZmNjQ2ZmZmZGZkMGZiOTM4YTMxNGM=
data/README.md CHANGED
@@ -353,7 +353,7 @@ Person.first.teams
353
353
 
354
354
  ##### Original association
355
355
 
356
- The original association is renamed to "original_association_name". So, the
356
+ The original association is renamed to `original_association_name`. So, the
357
357
  original association of the deferred association named `teams` can be accessed
358
358
  by using `original_teams`.
359
359
 
data/lib/deferring.rb CHANGED
@@ -25,9 +25,10 @@ module Deferring
25
25
  def deferred_has_many(*args)
26
26
  options = args.extract_options!
27
27
  listeners = create_callback_listeners!(options)
28
+ inverse_association_name = options.fetch(:as, self.name.underscore.to_sym)
28
29
 
29
30
  has_many(*args, options)
30
- generate_deferred_association_methods(args.first.to_s, listeners)
31
+ generate_deferred_association_methods(args.first.to_s, listeners, inverse_association_name)
31
32
  end
32
33
 
33
34
  def deferred_accepts_nested_attributes_for(*args)
@@ -36,7 +37,7 @@ module Deferring
36
37
 
37
38
  # teams_attributes=
38
39
  define_method :"#{association_name}_attributes=" do |records|
39
- find_or_create_deferred_association(association_name, [])
40
+ find_or_create_deferred_association(association_name, [], nil)
40
41
 
41
42
  # Remove the records that are to be destroyed from the ids that are to be
42
43
  # assigned to the DeferredAssociation instance.
@@ -52,7 +53,7 @@ module Deferring
52
53
 
53
54
  private
54
55
 
55
- def generate_deferred_association_methods(association_name, listeners)
56
+ def generate_deferred_association_methods(association_name, listeners, inverse_association_name = nil)
56
57
  # Store the original accessor methods of the association.
57
58
  alias_method :"original_#{association_name}", :"#{association_name}"
58
59
  alias_method :"original_#{association_name}=", :"#{association_name}="
@@ -66,7 +67,7 @@ module Deferring
66
67
  # if none are found.
67
68
  # TODO: add force_reload argument?
68
69
  define_method :"#{association_name}" do
69
- find_or_create_deferred_association(association_name, listeners)
70
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
70
71
  send(:"deferred_#{association_name}")
71
72
  end
72
73
 
@@ -75,7 +76,7 @@ module Deferring
75
76
  # Replaces the collection's content by deleting and adding objects as
76
77
  # appropriate.
77
78
  define_method :"#{association_name}=" do |objects|
78
- find_or_create_deferred_association(association_name, listeners)
79
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
79
80
  send(:"deferred_#{association_name}").objects = objects
80
81
  end
81
82
 
@@ -84,7 +85,7 @@ module Deferring
84
85
  # Replace the collection by the objects identified by the primary keys in
85
86
  # ids.
86
87
  define_method :"#{association_name.singularize}_ids=" do |ids|
87
- find_or_create_deferred_association(association_name, listeners)
88
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
88
89
 
89
90
  klass = self.class.reflect_on_association(:"#{association_name}").klass
90
91
  objects = klass.find(ids.reject(&:blank?))
@@ -95,13 +96,13 @@ module Deferring
95
96
  #
96
97
  # Returns an array of the associated objects' ids.
97
98
  define_method :"#{association_name.singularize}_ids" do
98
- find_or_create_deferred_association(association_name, listeners)
99
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
99
100
  send(:"deferred_#{association_name}").ids
100
101
  end
101
102
 
102
- # collection_singalur_checked
103
+ # collection_singular_checked
103
104
  attr_accessor :"#{association_name}_checked"
104
- # collection_singalur_checked=
105
+ # collection_singular_checked=
105
106
  define_method(:"#{association_name}_checked=") do |ids|
106
107
  send(:"#{association_name.singularize}_ids=", ids.split(','))
107
108
  end
@@ -109,50 +110,47 @@ module Deferring
109
110
  # the save after the parent object has been saved
110
111
  after_save :"perform_deferred_#{association_name}_save!"
111
112
  define_method :"perform_deferred_#{association_name}_save!" do
112
- find_or_create_deferred_association(association_name, listeners)
113
+
114
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
113
115
 
114
116
  # Send the objects of our delegated association to the original
115
117
  # association and store the result.
116
118
  send(:"original_#{association_name}=", send(:"deferred_#{association_name}").objects)
117
119
 
118
120
  # Store the new value of the association into our delegated association.
119
- send(
120
- :"deferred_#{association_name}=",
121
- DeferredAssociation.new(send(:"original_#{association_name}"), association_name))
122
- listeners.each do |event_name, callback_method|
123
- l = DeferredCallbackListener.new(event_name, self, callback_method)
124
- send(:"deferred_#{association_name}").add_callback_listener(l)
125
- end
121
+ save_deferred_association(association_name, listeners, inverse_association_name)
126
122
  end
127
123
 
128
124
  define_method :"reload_with_deferred_#{association_name}" do |*args|
129
- find_or_create_deferred_association(association_name, listeners)
125
+ find_or_create_deferred_association(association_name, listeners, inverse_association_name)
130
126
 
131
127
  send(:"reload_without_deferred_#{association_name}", *args).tap do
132
- send(
133
- :"deferred_#{association_name}=",
134
- DeferredAssociation.new(send(:"original_#{association_name}"), association_name))
135
- listeners.each do |event_name, callback_method|
136
- l = DeferredCallbackListener.new(event_name, self, callback_method)
137
- send(:"deferred_#{association_name}").add_callback_listener(l)
138
- end
128
+ save_deferred_association(association_name, listeners, inverse_association_name)
139
129
  end
140
130
  end
141
131
  alias_method_chain :reload, :"deferred_#{association_name}"
142
132
 
133
+ generate_save_deferred_assocation_method
143
134
  generate_find_or_create_deferred_association_method
144
135
  end
145
136
 
137
+ def generate_save_deferred_assocation_method
138
+ define_method :save_deferred_association do |name, listeners, inverse_association_name|
139
+ klass = self.class.reflect_on_association(:"#{name}").klass
140
+ send(
141
+ :"deferred_#{name}=",
142
+ DeferredAssociation.new(send(:"original_#{name}"), klass, self, inverse_association_name))
143
+ listeners.each do |event_name, callback_method|
144
+ l = DeferredCallbackListener.new(event_name, self, callback_method)
145
+ send(:"deferred_#{name}").add_callback_listener(l)
146
+ end
147
+ end
148
+ end
149
+
146
150
  def generate_find_or_create_deferred_association_method
147
- define_method :find_or_create_deferred_association do |name, listeners|
151
+ define_method :find_or_create_deferred_association do |name, listeners, inverse_association_name|
148
152
  if send(:"deferred_#{name}").nil?
149
- send(
150
- :"deferred_#{name}=",
151
- DeferredAssociation.new(send(:"original_#{name}"), name))
152
- listeners.each do |event_name, callback_method|
153
- l = DeferredCallbackListener.new(event_name, self, callback_method)
154
- send(:"deferred_#{name}").add_callback_listener(l)
155
- end
153
+ save_deferred_association(name, listeners, inverse_association_name)
156
154
  end
157
155
  end
158
156
  end
@@ -7,12 +7,14 @@ module Deferring
7
7
  # TODO: Write tests for enumerable.
8
8
  include Enumerable
9
9
 
10
- attr_reader :load_state
10
+ attr_reader :load_state, :klass, :parent_record, :inverse_name
11
11
 
12
- def initialize(original_association, name)
12
+ def initialize(original_association, klass, parent_record, inverse_name)
13
13
  super(original_association)
14
- @name = name
15
- @load_state = :ghost
14
+ @load_state = :ghost
15
+ @klass = klass
16
+ @parent_record = parent_record
17
+ @inverse_name = inverse_name
16
18
  end
17
19
  alias_method :original_association, :__getobj__
18
20
 
@@ -111,14 +113,13 @@ module Deferring
111
113
  end
112
114
 
113
115
  def build(*args, &block)
114
- association.build(*args, &block).tap do |record|
116
+ klass.new(*args, &block).tap do |record|
115
117
  run_deferring_callbacks(:link, record) do
116
- objects.push(record)
118
+ if inverse_name && record.class.reflect_on_association(inverse_name)
119
+ record.send(:"#{inverse_name}=", parent_record)
120
+ end
117
121
 
118
- # Remove the newly build record from the original association. If we
119
- # didn't do this, the new record would be saved to the database when
120
- # saving the parent object (and not after, as we want).
121
- association.reload
122
+ objects.push(record)
122
123
  end
123
124
  end
124
125
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Deferring
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.5'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe 'deferred has-and-belongs-to-many associations' do
3
+ RSpec.describe 'deferred has_and_belongs_to_many associations' do
4
4
 
5
5
  before :each do
6
6
  Person.create!(name: 'Alice')
@@ -127,6 +127,43 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
127
127
  end
128
128
  end
129
129
 
130
+ xit 'deferred habtm <=> regular habtm' do
131
+ alice = Person.where(name: 'Alice').first
132
+ bob = Person.where(name: 'Bob').first
133
+
134
+ team = Team.first
135
+ team.people << alice << bob
136
+ team.save!
137
+
138
+ bob.reload
139
+ expect(bob.teams.size).to eq(1)
140
+
141
+ alice.reload
142
+ expect(alice.teams.size).to eq(1)
143
+
144
+ team.people.create!(name: 'Chuck')
145
+ expect(team).to_not be_valid
146
+
147
+ bob.reload
148
+ alice.reload
149
+
150
+ expect(bob).to_not be_valid
151
+ expect(alice).to_not be_valid
152
+
153
+ expect(bob.save).to be_falsey
154
+ expect(alice.save).to be_falsey
155
+ end
156
+
157
+ xit 'does not validate records when validate: false' do
158
+ pending 'validate: false does not work' do
159
+ alice = Person.where(name: 'Alice').first
160
+ alice.teams.build(name: nil)
161
+ alice.save!
162
+
163
+ expect(alice.teams.size).to eq 1
164
+ end
165
+ end
166
+
130
167
  end
131
168
 
132
169
  describe 'preloading' do
@@ -277,13 +314,13 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
277
314
  describe 'callbacks' do
278
315
 
279
316
  before(:example) do
280
- bob = Person.first
317
+ bob = Person.where(name: 'Bob').first
281
318
  bob.teams = [Team.find(3)]
282
319
  bob.save!
283
320
  end
284
321
 
285
322
  it 'calls the link callbacks when adding a record using <<' do
286
- bob = Person.first
323
+ bob = Person.where(name: 'Bob').first
287
324
  bob.teams << Team.find(1)
288
325
 
289
326
  expect(bob.audit_log.length).to eq(2)
@@ -294,7 +331,7 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
294
331
  end
295
332
 
296
333
  it 'calls the link callbacks when adding a record using push' do
297
- bob = Person.first
334
+ bob = Person.where(name: 'Bob').first
298
335
  bob.teams.push(Team.find(1))
299
336
 
300
337
  expect(bob.audit_log.length).to eq(2)
@@ -305,7 +342,7 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
305
342
  end
306
343
 
307
344
  it 'calls the link callbacks when adding a record using append' do
308
- bob = Person.first
345
+ bob = Person.where(name: 'Bob').first
309
346
  bob.teams.append(Team.find(1))
310
347
 
311
348
  expect(bob.audit_log.length).to eq(2)
@@ -315,8 +352,19 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
315
352
  ])
316
353
  end
317
354
 
355
+ it 'calls the link callbacks when adding a record using build' do
356
+ bob = Person.where(name: 'Bob').first
357
+ bob.teams.build(name: 'Foooo')
358
+
359
+ expect(bob.audit_log.length).to eq(2)
360
+ expect(bob.audit_log).to eq([
361
+ 'Before linking new team',
362
+ 'After linking new team'
363
+ ])
364
+ end
365
+
318
366
  it 'only calls the Rails callbacks when creating a record on the association using create' do
319
- bob = Person.first
367
+ bob = Person.where(name: 'Bob').first
320
368
  bob.teams.create(name: 'HR')
321
369
 
322
370
  expect(bob.audit_log.length).to eq(2)
@@ -327,7 +375,7 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
327
375
  end
328
376
 
329
377
  it 'only calls the Rails callbacks when creating a record on the association using create!' do
330
- bob = Person.first
378
+ bob = Person.where(name: 'Bob').first
331
379
  bob.teams.create!(name: 'HR')
332
380
 
333
381
  expect(bob.audit_log.length).to eq(2)
@@ -338,7 +386,7 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
338
386
  end
339
387
 
340
388
  it 'calls the unlink callbacks when removing a record using delete' do
341
- bob = Person.first
389
+ bob = Person.where(name: 'Bob').first
342
390
  bob.teams.delete(Team.find(3))
343
391
 
344
392
  expect(bob.audit_log.length).to eq(2)
@@ -349,7 +397,7 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
349
397
  end
350
398
 
351
399
  it 'only calls the rails callbacks when removing a record using destroy' do
352
- bob = Person.first
400
+ bob = Person.where(name: 'Bob').first
353
401
  bob.teams.destroy(3)
354
402
 
355
403
  expect(bob.audit_log.length).to eq(2)
@@ -360,23 +408,24 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
360
408
  end
361
409
 
362
410
  it 'calls the regular Rails callbacks after saving' do
363
- bob = Person.first
411
+ bob = Person.where(name: 'Bob').first
364
412
  bob.teams = [Team.find(1), Team.find(3)]
365
413
  bob.save!
366
414
 
367
- bob = Person.first
415
+ bob = Person.where(name: 'Bob').first
368
416
  bob.teams.delete(Team.find(1))
369
417
  bob.teams << Team.find(2)
418
+ bob.teams.build(name: 'Service Desk')
370
419
  bob.save!
371
420
 
372
- expect(bob.audit_log.length).to eq(8)
421
+ expect(bob.audit_log.length).to eq(12)
373
422
  expect(bob.audit_log).to eq([
374
423
  'Before unlinking team 1', 'After unlinking team 1',
375
- 'Before linking team 2', 'After linking team 2',
376
- 'Before removing team 1',
377
- 'After removing team 1',
378
- 'Before adding team 2',
379
- 'After adding team 2'
424
+ 'Before linking team 2', 'After linking team 2',
425
+ 'Before linking new team', 'After linking new team',
426
+ 'Before removing team 1', 'After removing team 1',
427
+ 'Before adding team 2', 'After adding team 2',
428
+ 'Before adding new team', 'After adding team 4'
380
429
  ])
381
430
  end
382
431
 
@@ -460,8 +509,6 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
460
509
 
461
510
  end
462
511
 
463
- # TODO: Clean up tests.
464
-
465
512
  describe 'active record api' do
466
513
 
467
514
  # it 'should execute first on deferred association' do
@@ -480,28 +527,33 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
480
527
  # expect(Person.first.teams.last).to eq(operations)
481
528
  # end
482
529
 
483
- it 'should build a new record' do
484
- p = Person.first
485
- p.teams.build(name: 'Service Desk')
486
- expect(p.teams[0]).to be_new_record
487
- end
530
+ describe '#build' do
531
+
532
+ it 'builds a new record' do
533
+ p = Person.first
534
+ p.teams.build(name: 'Service Desk')
535
+
536
+ expect(p.teams[0]).to be_new_record
537
+ expect{ p.save }.to change{ Person.first.teams.count }.from(0).to(1)
538
+ end
488
539
 
489
- it 'should build and save a new record' do
490
- p = Person.first
491
- p.teams.build(name: 'Service Desk')
492
- expect(p.teams[0]).to be_new_record
493
- expect(Person.first.teams.size).to eq(0)
494
- p.save
495
- expect(Person.first.teams.size).to eq(1)
496
540
  end
497
541
 
498
- it 'should add a new record' do
499
- p = Person.first
500
- p.teams.create!(:name => 'Service Desk')
501
- expect(p.teams[0]).to_not be_new_record
502
- expect(Person.first.teams.size).to eq(1)
503
- p.save
504
- expect(Person.first.teams.size).to eq(1)
542
+ describe '#create!' do
543
+
544
+ it 'should create a persisted record' do
545
+ p = Person.first
546
+ p.teams.create!(:name => 'Service Desk')
547
+ expect(p.teams[0]).to_not be_new_record
548
+ end
549
+
550
+ it 'should automatically save the created record' do
551
+ p = Person.first
552
+ p.teams.create!(:name => 'Service Desk')
553
+ expect(Person.first.teams.size).to eq(1)
554
+ expect{ p.save }.to_not change{ Person.first.teams.count }
555
+ end
556
+
505
557
  end
506
558
 
507
559
  it 'should allow ActiveRecord::QueryMethods' do
@@ -525,101 +577,4 @@ RSpec.describe 'deferred has-and-belongs-to-many associations' do
525
577
 
526
578
  end
527
579
 
528
- describe 'accepts_nested_attributes' do
529
- # TODO: Write more tests.
530
- it 'should mass assign' do
531
- p = Person.first
532
- p.teams << Team.first << Team.last << Team.find(2)
533
- p.save
534
-
535
- # Destroy team 2 and 3. Keep team 1.
536
- p = Person.first
537
- p.attributes = {
538
- teams_attributes: [
539
- { id: 1 },
540
- { id: 3, _destroy: true },
541
- { id: 2, _destroy: true }
542
- ]
543
- }
544
- expect(p.teams.length).to eq(1)
545
- expect(p.team_ids.sort).to eq([1])
546
-
547
- Person.first
548
- expect(Person.first.teams.length).to eq(3)
549
- expect(Person.first.team_ids.sort).to eq([1,2,3])
550
-
551
- p.save!
552
-
553
- p = Person.first
554
- expect(p.teams.length).to eq(1)
555
- expect(p.team_ids.sort).to eq([1])
556
- end
557
-
558
- it 'should mass assign' do
559
- p = Person.first
560
- p.teams << Team.first << Team.last << Team.find(2)
561
- p.save
562
-
563
- # Destroy team 2 and 3. Keep team 1.
564
- p = Person.first
565
- p.teams_attributes = [
566
- { id: 1 },
567
- { id: 3, _destroy: true },
568
- { id: 2, _destroy: true }
569
- ]
570
- expect(p.teams.length).to eq(1)
571
- expect(p.team_ids.sort).to eq([1])
572
-
573
- Person.first
574
- expect(Person.first.teams.length).to eq(3)
575
- expect(Person.first.team_ids.sort).to eq([1,2,3])
576
-
577
- p.save!
578
-
579
- p = Person.first
580
- expect(p.teams.length).to eq(1)
581
- expect(p.team_ids.sort).to eq([1])
582
- end
583
- end
584
-
585
- describe 'validations' do
586
-
587
- xit 'deferred habtm <=> regular habtm' do
588
- alice = Person.where(name: 'Alice').first
589
- bob = Person.where(name: 'Bob').first
590
-
591
- team = Team.first
592
- team.people << alice << bob
593
- team.save!
594
-
595
- bob.reload
596
- expect(bob.teams.size).to eq(1)
597
-
598
- alice.reload
599
- expect(alice.teams.size).to eq(1)
600
-
601
- team.people.create!(name: 'Chuck')
602
- expect(team).to_not be_valid
603
-
604
- bob.reload
605
- alice.reload
606
-
607
- expect(bob).to_not be_valid
608
- expect(alice).to_not be_valid
609
-
610
- expect(bob.save).to be_falsey
611
- expect(alice.save).to be_falsey
612
- end
613
-
614
- xit 'does not validate records when validate: false' do
615
- pending 'validate: false does not work' do
616
- alice = Person.where(name: 'Alice').first
617
- alice.teams.build(name: nil)
618
- alice.save!
619
-
620
- expect(alice.teams.size).to eq 1
621
- end
622
- end
623
- end
624
-
625
580
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe 'deferred has-many association' do
3
+ RSpec.describe 'deferred has_many associations' do
4
4
 
5
5
  before(:each) do
6
6
  Person.create!(name: 'Alice')
@@ -17,43 +17,62 @@ RSpec.describe 'deferred has-many association' do
17
17
 
18
18
  describe 'preloading associations' do
19
19
  before do
20
- p = Person.find(1)
21
- p.issues << printer_issue << db_issue
22
- p.save!
20
+ bob = Person.where(name: 'Bob').first
21
+ bob.issues << printer_issue << db_issue
22
+ bob.save!
23
23
  end
24
24
 
25
25
  if rails30 # old-style preload
26
26
  it 'should have loaded the association' do
27
- p = Person.find(1)
28
- Person.send(:preload_associations, p, [:issues])
29
- expect(p.issues.loaded?).to be_truthy
30
- expect(p.issue_ids).to eq [printer_issue.id, db_issue.id]
27
+ bob = Person.where(name: 'Bob').first
28
+ Person.send(:preload_associations, bob, [:issues])
29
+ expect(bob.issues.loaded?).to be_truthy
30
+ expect(bob.issue_ids).to eq [printer_issue.id, db_issue.id]
31
31
  end
32
32
  end
33
33
 
34
34
  if rails32 || rails4
35
35
  it 'should have loaded the association when pre-loading' do
36
36
  people = Person.preload(:issues)
37
- expect(people[0].issues.loaded?).to be_truthy
38
- expect(people[0].issue_ids).to eq [printer_issue.id, db_issue.id]
37
+ expect(people[1].issues.loaded?).to be_truthy
38
+ expect(people[1].issue_ids).to eq [printer_issue.id, db_issue.id]
39
39
  end
40
40
 
41
41
  it 'should have loaded the association when eager loading' do
42
42
  people = Person.eager_load(:issues)
43
- expect(people[0].issues.loaded?).to be_truthy
44
- expect(people[0].issue_ids).to eq [db_issue.id, printer_issue.id]
43
+ expect(people[1].issues.loaded?).to be_truthy
44
+ expect(people[1].issue_ids).to eq [db_issue.id, printer_issue.id]
45
45
  end
46
46
 
47
47
  it 'should have loaded the association when joining' do
48
48
  people = Person.includes(:issues).all
49
- expect(people[0].issues.loaded?).to be_truthy
50
- expect(people[0].issue_ids).to eq [printer_issue.id, db_issue.id]
49
+ expect(people[1].issues.loaded?).to be_truthy
50
+ expect(people[1].issue_ids).to eq [printer_issue.id, db_issue.id]
51
51
  end
52
52
  end
53
53
 
54
54
  it 'should not have loaded the association when using a regular query' do
55
55
  people = Person.all
56
- expect(people[0].issues.loaded?).to be_falsey
56
+ expect(people[1].issues.loaded?).to be_falsey
57
+ end
58
+ end
59
+
60
+ describe 'active record api' do
61
+
62
+ describe '#build' do
63
+ it 'builds a new record' do
64
+ bob = Person.where(name: 'Bob').first
65
+ bob.issues.build(subject: 'I need coffee!')
66
+
67
+ expect(bob.issues.last).to be_new_record
68
+ end
69
+
70
+ it 'sets the belongs_to association of the built record' do
71
+ bob = Person.where(name: 'Bob').first
72
+ bob.issues.build(subject: 'I need coffee!')
73
+
74
+ expect(bob.issues.last.person).to eq bob
75
+ end
57
76
  end
58
77
  end
59
78
 
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'deferred accepts_nested_attributes' do
4
+
5
+ before :each do
6
+ Person.create!(name: 'Alice')
7
+ Person.create!(name: 'Bob')
8
+
9
+ Team.create!(name: 'Database Administration')
10
+ Team.create!(name: 'End-User Support')
11
+ Team.create!(name: 'Operations')
12
+ end
13
+
14
+ let(:bob) { Person.where(name: 'Bob').first }
15
+
16
+ let(:dba) { Team.where(name: 'Database Administration').first }
17
+ let(:support) { Team.where(name: 'End-User Support').first }
18
+ let(:operations) { Team.where(name: 'Operations').first }
19
+
20
+ # TODO: Write more tests.
21
+
22
+ it 'should mass assign' do
23
+ p = Person.first
24
+ p.teams << Team.first << Team.last << Team.find(2)
25
+ p.save
26
+
27
+ # Destroy team 2 and 3. Keep team 1.
28
+ p = Person.first
29
+ p.attributes = {
30
+ teams_attributes: [
31
+ { id: 1 },
32
+ { id: 3, _destroy: true },
33
+ { id: 2, _destroy: true }
34
+ ]
35
+ }
36
+ expect(p.teams.length).to eq(1)
37
+ expect(p.team_ids.sort).to eq([1])
38
+
39
+ Person.first
40
+ expect(Person.first.teams.length).to eq(3)
41
+ expect(Person.first.team_ids.sort).to eq([1,2,3])
42
+
43
+ p.save!
44
+
45
+ p = Person.first
46
+ expect(p.teams.length).to eq(1)
47
+ expect(p.team_ids.sort).to eq([1])
48
+ end
49
+
50
+ end
@@ -28,11 +28,19 @@ class Person < ActiveRecord::Base
28
28
  end
29
29
 
30
30
  def link_team(team)
31
- log("Before linking team #{team.id}")
31
+ if team.new_record?
32
+ log("Before linking new team")
33
+ else
34
+ log("Before linking team #{team.id}")
35
+ end
32
36
  end
33
37
 
34
38
  def linked_team(team)
35
- log("After linking team #{team.id}")
39
+ if team.new_record?
40
+ log("After linking new team")
41
+ else
42
+ log("After linking team #{team.id}")
43
+ end
36
44
  end
37
45
 
38
46
  def unlink_team(team)
@@ -63,11 +71,11 @@ class Person < ActiveRecord::Base
63
71
  log("After removing team #{team.id}")
64
72
  end
65
73
 
66
- def add_issue(issue)
74
+ def remove_issue(issue)
67
75
  log("Before removing issue #{issue.id}")
68
76
  end
69
77
 
70
- def added_issue(issue)
78
+ def removed_issue(issue)
71
79
  log("After removing issue #{issue.id}")
72
80
  end
73
81
  end
metadata CHANGED
@@ -1,100 +1,100 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deferring
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
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-01 00:00:00.000000000 Z
11
+ date: 2014-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">"
17
+ - - ! '>'
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.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
26
  version: '3.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - ! '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: appraisal
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - ! '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - ! '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: "\n The Deferring gem makes it possible to defer saving ActiveRecord\n
97
+ description: ! "\n The Deferring gem makes it possible to defer saving ActiveRecord\n
98
98
  \ associations until the parent object is saved.\n "
99
99
  email:
100
100
  - robin@roestenburg.io
@@ -102,9 +102,9 @@ executables: []
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
- - ".gitignore"
106
- - ".rspec"
107
- - ".travis.yml"
105
+ - .gitignore
106
+ - .rspec
107
+ - .travis.yml
108
108
  - Appraisals
109
109
  - Gemfile
110
110
  - LICENSE.txt
@@ -115,8 +115,6 @@ files:
115
115
  - gemfiles/rails_30.gemfile.lock
116
116
  - gemfiles/rails_32.gemfile
117
117
  - gemfiles/rails_32.gemfile.lock
118
- - gemfiles/rails_4.gemfile
119
- - gemfiles/rails_4.gemfile.lock
120
118
  - gemfiles/rails_40.gemfile
121
119
  - gemfiles/rails_40.gemfile.lock
122
120
  - gemfiles/rails_41.gemfile
@@ -125,8 +123,9 @@ files:
125
123
  - lib/deferring/deferred_association.rb
126
124
  - lib/deferring/deferred_callback_listener.rb
127
125
  - lib/deferring/version.rb
126
+ - spec/lib/deferring_habtm_spec.rb
128
127
  - spec/lib/deferring_has_many_spec.rb
129
- - spec/lib/deferring_spec.rb
128
+ - spec/lib/deferring_nested_attributes_spec.rb
130
129
  - spec/spec_helper.rb
131
130
  - spec/support/active_record.rb
132
131
  - spec/support/models.rb
@@ -141,23 +140,24 @@ require_paths:
141
140
  - lib
142
141
  required_ruby_version: !ruby/object:Gem::Requirement
143
142
  requirements:
144
- - - ">="
143
+ - - ! '>='
145
144
  - !ruby/object:Gem::Version
146
145
  version: '0'
147
146
  required_rubygems_version: !ruby/object:Gem::Requirement
148
147
  requirements:
149
- - - ">="
148
+ - - ! '>='
150
149
  - !ruby/object:Gem::Version
151
150
  version: '0'
152
151
  requirements: []
153
152
  rubyforge_project:
154
- rubygems_version: 2.2.2
153
+ rubygems_version: 2.4.1
155
154
  signing_key:
156
155
  specification_version: 4
157
156
  summary: Defer saving ActiveRecord associations until parent is saved
158
157
  test_files:
158
+ - spec/lib/deferring_habtm_spec.rb
159
159
  - spec/lib/deferring_has_many_spec.rb
160
- - spec/lib/deferring_spec.rb
160
+ - spec/lib/deferring_nested_attributes_spec.rb
161
161
  - spec/spec_helper.rb
162
162
  - spec/support/active_record.rb
163
163
  - spec/support/models.rb
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "4.1.0"
6
-
7
- gemspec :path => "../"
@@ -1,58 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- raincheck (0.0.1)
5
- activerecord (> 3.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (4.1.0)
11
- activesupport (= 4.1.0)
12
- builder (~> 3.1)
13
- activerecord (4.1.0)
14
- activemodel (= 4.1.0)
15
- activesupport (= 4.1.0)
16
- arel (~> 5.0.0)
17
- activesupport (4.1.0)
18
- i18n (~> 0.6, >= 0.6.9)
19
- json (~> 1.7, >= 1.7.7)
20
- minitest (~> 5.1)
21
- thread_safe (~> 0.1)
22
- tzinfo (~> 1.1)
23
- appraisal (1.0.0)
24
- bundler
25
- rake
26
- thor (>= 0.14.0)
27
- arel (5.0.1.20140414130214)
28
- builder (3.2.2)
29
- diff-lcs (1.2.5)
30
- i18n (0.6.9)
31
- json (1.8.1)
32
- minitest (5.3.3)
33
- rake (10.3.1)
34
- rspec (2.14.1)
35
- rspec-core (~> 2.14.0)
36
- rspec-expectations (~> 2.14.0)
37
- rspec-mocks (~> 2.14.0)
38
- rspec-core (2.14.8)
39
- rspec-expectations (2.14.5)
40
- diff-lcs (>= 1.1.3, < 2.0)
41
- rspec-mocks (2.14.6)
42
- sqlite3 (1.3.9)
43
- thor (0.19.1)
44
- thread_safe (0.3.3)
45
- tzinfo (1.1.0)
46
- thread_safe (~> 0.1)
47
-
48
- PLATFORMS
49
- ruby
50
-
51
- DEPENDENCIES
52
- activerecord (= 4.1.0)
53
- appraisal
54
- bundler (~> 1.3)
55
- raincheck!
56
- rake
57
- rspec
58
- sqlite3