deferring 0.0.4 → 0.0.5

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,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