~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activerecord/test/cases/nested_attributes_test.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
require "cases/helper"
2
 
require "models/pirate"
3
 
require "models/ship"
4
 
require "models/bird"
5
 
require "models/parrot"
6
 
require "models/treasure"
7
 
 
8
 
module AssertRaiseWithMessage
9
 
  def assert_raise_with_message(expected_exception, expected_message)
10
 
    begin
11
 
      error_raised = false
12
 
      yield
13
 
    rescue expected_exception => error
14
 
      error_raised = true
15
 
      actual_message = error.message
16
 
    end
17
 
    assert error_raised
18
 
    assert_equal expected_message, actual_message
19
 
  end
20
 
end
21
 
 
22
 
class TestNestedAttributesInGeneral < ActiveRecord::TestCase
23
 
  include AssertRaiseWithMessage
24
 
 
25
 
  def teardown
26
 
    Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
27
 
  end
28
 
 
29
 
  def test_base_should_have_an_empty_nested_attributes_options
30
 
    assert_equal Hash.new, ActiveRecord::Base.nested_attributes_options
31
 
  end
32
 
 
33
 
  def test_should_add_a_proc_to_nested_attributes_options
34
 
    [:parrots, :birds].each do |name|
35
 
      assert_instance_of Proc, Pirate.nested_attributes_options[name][:reject_if]
36
 
    end
37
 
  end
38
 
 
39
 
  def test_should_raise_an_ArgumentError_for_non_existing_associations
40
 
    assert_raise_with_message ArgumentError, "No association found for name `honesty'. Has it been defined yet?" do
41
 
      Pirate.accepts_nested_attributes_for :honesty
42
 
    end
43
 
  end
44
 
 
45
 
  def test_should_disable_allow_destroy_by_default
46
 
    Pirate.accepts_nested_attributes_for :ship
47
 
 
48
 
    pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
49
 
    ship = pirate.create_ship(:name => 'Nights Dirty Lightning')
50
 
 
51
 
    assert_no_difference('Ship.count') do
52
 
      pirate.update_attributes(:ship_attributes => { '_destroy' => true })
53
 
    end
54
 
  end
55
 
 
56
 
  def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction
57
 
    ship = Ship.create!(:name => 'Nights Dirty Lightning')
58
 
    assert !ship._destroy
59
 
    ship.mark_for_destruction
60
 
    assert ship._destroy
61
 
  end
62
 
 
63
 
  def test_underscore_delete_is_deprecated
64
 
    ActiveSupport::Deprecation.expects(:warn)
65
 
    ship = Ship.create!(:name => 'Nights Dirty Lightning')
66
 
    ship._delete
67
 
  end
68
 
 
69
 
  def test_reject_if_method_without_arguments
70
 
    Pirate.accepts_nested_attributes_for :ship, :reject_if => :new_record?
71
 
 
72
 
    pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
73
 
    pirate.ship_attributes = { :name => 'Black Pearl' }
74
 
    assert_no_difference('Ship.count') { pirate.save! }
75
 
  end
76
 
 
77
 
  def test_reject_if_method_with_arguments
78
 
    Pirate.accepts_nested_attributes_for :ship, :reject_if => :reject_empty_ships_on_create
79
 
 
80
 
    pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
81
 
    pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
82
 
    assert_no_difference('Ship.count') { pirate.save! }
83
 
 
84
 
    # pirate.reject_empty_ships_on_create returns false for saved records
85
 
    pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
86
 
    assert_difference('Ship.count') { pirate.save! }
87
 
  end
88
 
 
89
 
  def test_reject_if_with_indifferent_keys
90
 
    Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| attributes[:name].blank? }
91
 
 
92
 
    pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
93
 
    pirate.ship_attributes = { :name => 'Hello Pearl' }
94
 
    assert_difference('Ship.count') { pirate.save! }
95
 
  end
96
 
end
97
 
 
98
 
class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
99
 
  include AssertRaiseWithMessage
100
 
 
101
 
  def setup
102
 
    @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
103
 
    @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
104
 
  end
105
 
 
106
 
  def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to
107
 
    assert_raise_with_message ArgumentError, "Cannot build association looter. Are you trying to build a polymorphic one-to-one association?" do
108
 
      Treasure.new(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"})
109
 
    end
110
 
  end
111
 
 
112
 
  def test_should_define_an_attribute_writer_method_for_the_association
113
 
    assert_respond_to @pirate, :ship_attributes=
114
 
  end
115
 
 
116
 
  def test_should_build_a_new_record_if_there_is_no_id
117
 
    @ship.destroy
118
 
    @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' }
119
 
 
120
 
    assert @pirate.ship.new_record?
121
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
122
 
  end
123
 
 
124
 
  def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
125
 
    @ship.destroy
126
 
    @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
127
 
 
128
 
    assert_nil @pirate.ship
129
 
  end
130
 
 
131
 
  def test_should_not_build_a_new_record_if_a_reject_if_proc_returns_false
132
 
    @ship.destroy
133
 
    @pirate.reload.ship_attributes = {}
134
 
 
135
 
    assert_nil @pirate.ship
136
 
  end
137
 
 
138
 
  def test_should_replace_an_existing_record_if_there_is_no_id
139
 
    @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' }
140
 
 
141
 
    assert @pirate.ship.new_record?
142
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
143
 
    assert_equal 'Nights Dirty Lightning', @ship.name
144
 
  end
145
 
 
146
 
  def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
147
 
    @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
148
 
 
149
 
    assert_equal @ship, @pirate.ship
150
 
    assert_equal 'Nights Dirty Lightning', @pirate.ship.name
151
 
  end
152
 
 
153
 
  def test_should_modify_an_existing_record_if_there_is_a_matching_id
154
 
    @pirate.reload.ship_attributes = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
155
 
 
156
 
    assert_equal @ship, @pirate.ship
157
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
158
 
  end
159
 
 
160
 
  def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
161
 
    @pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' }
162
 
 
163
 
    assert_equal @ship, @pirate.ship
164
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
165
 
  end
166
 
 
167
 
  def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
168
 
    @ship.stubs(:id).returns('ABC1X')
169
 
    @pirate.ship_attributes = { :id => @ship.id, :name => 'Davy Jones Gold Dagger' }
170
 
 
171
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
172
 
  end
173
 
 
174
 
  def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
175
 
    @pirate.ship.destroy
176
 
    [1, '1', true, 'true'].each do |truth|
177
 
      @pirate.reload.create_ship(:name => 'Mister Pablo')
178
 
      assert_difference('Ship.count', -1) do
179
 
        @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => truth })
180
 
      end
181
 
    end
182
 
  end
183
 
 
184
 
  def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
185
 
    [nil, '0', 0, 'false', false].each do |not_truth|
186
 
      assert_no_difference('Ship.count') do
187
 
        @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => not_truth })
188
 
      end
189
 
    end
190
 
  end
191
 
 
192
 
  def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
193
 
    Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
194
 
 
195
 
    assert_no_difference('Ship.count') do
196
 
      @pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => '1' })
197
 
    end
198
 
 
199
 
    Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
200
 
  end
201
 
 
202
 
  def test_should_also_work_with_a_HashWithIndifferentAccess
203
 
    @pirate.ship_attributes = HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger')
204
 
 
205
 
    assert !@pirate.ship.new_record?
206
 
    assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
207
 
  end
208
 
 
209
 
  def test_should_work_with_update_attributes_as_well
210
 
    @pirate.update_attributes({ :catchphrase => 'Arr', :ship_attributes => { :id => @ship.id, :name => 'Mister Pablo' } })
211
 
    @pirate.reload
212
 
 
213
 
    assert_equal 'Arr', @pirate.catchphrase
214
 
    assert_equal 'Mister Pablo', @pirate.ship.name
215
 
  end
216
 
 
217
 
  def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
218
 
    assert_no_difference('Ship.count') do
219
 
      @pirate.attributes = { :ship_attributes => { :id => @ship.id, :_destroy => '1' } }
220
 
    end
221
 
    assert_difference('Ship.count', -1) do
222
 
      @pirate.save
223
 
    end
224
 
  end
225
 
 
226
 
  def test_should_automatically_enable_autosave_on_the_association
227
 
    assert Pirate.reflect_on_association(:ship).options[:autosave]
228
 
  end
229
 
end
230
 
 
231
 
class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
232
 
  def setup
233
 
    @ship = Ship.new(:name => 'Nights Dirty Lightning')
234
 
    @pirate = @ship.build_pirate(:catchphrase => 'Aye')
235
 
    @ship.save!
236
 
  end
237
 
 
238
 
  def test_should_define_an_attribute_writer_method_for_the_association
239
 
    assert_respond_to @ship, :pirate_attributes=
240
 
  end
241
 
 
242
 
  def test_should_build_a_new_record_if_there_is_no_id
243
 
    @pirate.destroy
244
 
    @ship.reload.pirate_attributes = { :catchphrase => 'Arr' }
245
 
 
246
 
    assert @ship.pirate.new_record?
247
 
    assert_equal 'Arr', @ship.pirate.catchphrase
248
 
  end
249
 
 
250
 
  def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
251
 
    @pirate.destroy
252
 
    @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
253
 
 
254
 
    assert_nil @ship.pirate
255
 
  end
256
 
 
257
 
  def test_should_not_build_a_new_record_if_a_reject_if_proc_returns_false
258
 
    @pirate.destroy
259
 
    @ship.reload.pirate_attributes = {}
260
 
 
261
 
    assert_nil @ship.pirate
262
 
  end
263
 
 
264
 
  def test_should_replace_an_existing_record_if_there_is_no_id
265
 
    @ship.reload.pirate_attributes = { :catchphrase => 'Arr' }
266
 
 
267
 
    assert @ship.pirate.new_record?
268
 
    assert_equal 'Arr', @ship.pirate.catchphrase
269
 
    assert_equal 'Aye', @pirate.catchphrase
270
 
  end
271
 
 
272
 
  def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
273
 
    @ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
274
 
 
275
 
    assert_equal @pirate, @ship.pirate
276
 
    assert_equal 'Aye', @ship.pirate.catchphrase
277
 
  end
278
 
 
279
 
  def test_should_modify_an_existing_record_if_there_is_a_matching_id
280
 
    @ship.reload.pirate_attributes = { :id => @pirate.id, :catchphrase => 'Arr' }
281
 
 
282
 
    assert_equal @pirate, @ship.pirate
283
 
    assert_equal 'Arr', @ship.pirate.catchphrase
284
 
  end
285
 
 
286
 
  def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
287
 
    @ship.reload.pirate_attributes = { 'id' => @pirate.id, 'catchphrase' => 'Arr' }
288
 
 
289
 
    assert_equal @pirate, @ship.pirate
290
 
    assert_equal 'Arr', @ship.pirate.catchphrase
291
 
  end
292
 
 
293
 
  def test_should_modify_an_existing_record_if_there_is_a_matching_composite_id
294
 
    @pirate.stubs(:id).returns('ABC1X')
295
 
    @ship.pirate_attributes = { :id => @pirate.id, :catchphrase => 'Arr' }
296
 
 
297
 
    assert_equal 'Arr', @ship.pirate.catchphrase
298
 
  end
299
 
 
300
 
  def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
301
 
    @ship.pirate.destroy
302
 
    [1, '1', true, 'true'].each do |truth|
303
 
      @ship.reload.create_pirate(:catchphrase => 'Arr')
304
 
      assert_difference('Pirate.count', -1) do
305
 
        @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => truth })
306
 
      end
307
 
    end
308
 
  end
309
 
 
310
 
  def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
311
 
    [nil, '0', 0, 'false', false].each do |not_truth|
312
 
      assert_no_difference('Pirate.count') do
313
 
        @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => not_truth })
314
 
      end
315
 
    end
316
 
  end
317
 
 
318
 
  def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
319
 
    Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
320
 
 
321
 
    assert_no_difference('Pirate.count') do
322
 
      @ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => '1' })
323
 
    end
324
 
 
325
 
    Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
326
 
  end
327
 
 
328
 
  def test_should_work_with_update_attributes_as_well
329
 
    @ship.update_attributes({ :name => 'Mister Pablo', :pirate_attributes => { :catchphrase => 'Arr' } })
330
 
    @ship.reload
331
 
 
332
 
    assert_equal 'Mister Pablo', @ship.name
333
 
    assert_equal 'Arr', @ship.pirate.catchphrase
334
 
  end
335
 
 
336
 
  def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
337
 
    assert_no_difference('Pirate.count') do
338
 
      @ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_destroy' => true } }
339
 
    end
340
 
    assert_difference('Pirate.count', -1) { @ship.save }
341
 
  end
342
 
 
343
 
  def test_should_automatically_enable_autosave_on_the_association
344
 
    assert Ship.reflect_on_association(:pirate).options[:autosave]
345
 
  end
346
 
end
347
 
 
348
 
module NestedAttributesOnACollectionAssociationTests
349
 
  include AssertRaiseWithMessage
350
 
 
351
 
  def test_should_define_an_attribute_writer_method_for_the_association
352
 
    assert_respond_to @pirate, association_setter
353
 
  end
354
 
 
355
 
  def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models
356
 
    @alternate_params[association_getter].stringify_keys!
357
 
    @pirate.update_attributes @alternate_params
358
 
    assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
359
 
  end
360
 
 
361
 
  def test_should_take_an_array_and_assign_the_attributes_to_the_associated_models
362
 
    @pirate.send(association_setter, @alternate_params[association_getter].values)
363
 
    @pirate.save
364
 
    assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
365
 
  end
366
 
 
367
 
  def test_should_also_work_with_a_HashWithIndifferentAccess
368
 
    @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley')))
369
 
    @pirate.save
370
 
    assert_equal 'Grace OMalley', @child_1.reload.name
371
 
  end
372
 
 
373
 
  def test_should_take_a_hash_and_assign_the_attributes_to_the_associated_models
374
 
    @pirate.attributes = @alternate_params
375
 
    assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
376
 
    assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
377
 
  end
378
 
 
379
 
  def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models
380
 
    @child_1.stubs(:id).returns('ABC1X')
381
 
    @child_2.stubs(:id).returns('ABC2X')
382
 
 
383
 
    @pirate.attributes = {
384
 
      association_getter => [
385
 
        { :id => @child_1.id, :name => 'Grace OMalley' },
386
 
        { :id => @child_2.id, :name => 'Privateers Greed' }
387
 
      ]
388
 
    }
389
 
 
390
 
    assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name]
391
 
  end
392
 
 
393
 
  def test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing
394
 
    @pirate.send(@association_name).destroy_all
395
 
    @pirate.reload.attributes = {
396
 
      association_getter => { 'foo' => { :name => 'Grace OMalley' }, 'bar' => { :name => 'Privateers Greed' }}
397
 
    }
398
 
 
399
 
    assert @pirate.send(@association_name).first.new_record?
400
 
    assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
401
 
 
402
 
    assert @pirate.send(@association_name).last.new_record?
403
 
    assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
404
 
  end
405
 
 
406
 
  def test_should_not_assign_destroy_key_to_a_record
407
 
    assert_nothing_raised ActiveRecord::UnknownAttributeError do
408
 
      @pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
409
 
    end
410
 
  end
411
 
 
412
 
  def test_should_ignore_new_associated_records_with_truthy_destroy_attribute
413
 
    @pirate.send(@association_name).destroy_all
414
 
    @pirate.reload.attributes = {
415
 
      association_getter => {
416
 
        'foo' => { :name => 'Grace OMalley' },
417
 
        'bar' => { :name => 'Privateers Greed', '_destroy' => '1' }
418
 
      }
419
 
    }
420
 
 
421
 
    assert_equal 1, @pirate.send(@association_name).length
422
 
    assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
423
 
  end
424
 
 
425
 
  def test_should_ignore_new_associated_records_if_a_reject_if_proc_returns_false
426
 
    @alternate_params[association_getter]['baz'] = {}
427
 
    assert_no_difference("@pirate.send(@association_name).length") do
428
 
      @pirate.attributes = @alternate_params
429
 
    end
430
 
  end
431
 
 
432
 
  def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
433
 
    attributes = ActiveSupport::OrderedHash.new
434
 
    attributes['123726353'] = { :name => 'Grace OMalley' }
435
 
    attributes['2'] = { :name => 'Privateers Greed' } # 2 is lower then 123726353
436
 
    @pirate.send(association_setter, attributes)
437
 
 
438
 
    assert_equal ['Posideons Killer', 'Killer bandita Dionne', 'Privateers Greed', 'Grace OMalley'].to_set, @pirate.send(@association_name).map(&:name).to_set
439
 
  end
440
 
 
441
 
  def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
442
 
    assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, {}) }
443
 
    assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, ActiveSupport::OrderedHash.new) }
444
 
 
445
 
    assert_raise_with_message ArgumentError, 'Hash or Array expected, got String ("foo")' do
446
 
      @pirate.send(association_setter, "foo")
447
 
    end
448
 
  end
449
 
 
450
 
  def test_should_work_with_update_attributes_as_well
451
 
    @pirate.update_attributes(:catchphrase => 'Arr',
452
 
      association_getter => { 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' }})
453
 
 
454
 
    assert_equal 'Grace OMalley', @child_1.reload.name
455
 
  end
456
 
 
457
 
  def test_should_update_existing_records_and_add_new_ones_that_have_no_id
458
 
    @alternate_params[association_getter]['baz'] = { :name => 'Buccaneers Servant' }
459
 
    assert_difference('@pirate.send(@association_name).count', +1) do
460
 
      @pirate.update_attributes @alternate_params
461
 
    end
462
 
    assert_equal ['Grace OMalley', 'Privateers Greed', 'Buccaneers Servant'].to_set, @pirate.reload.send(@association_name).map(&:name).to_set
463
 
  end
464
 
 
465
 
  def test_should_be_possible_to_destroy_a_record
466
 
    ['1', 1, 'true', true].each do |true_variable|
467
 
      record = @pirate.reload.send(@association_name).create!(:name => 'Grace OMalley')
468
 
      @pirate.send(association_setter,
469
 
        @alternate_params[association_getter].merge('baz' => { :id => record.id, '_destroy' => true_variable })
470
 
      )
471
 
 
472
 
      assert_difference('@pirate.send(@association_name).count', -1) do
473
 
        @pirate.save
474
 
      end
475
 
    end
476
 
  end
477
 
 
478
 
  def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument
479
 
    [nil, '', '0', 0, 'false', false].each do |false_variable|
480
 
      @alternate_params[association_getter]['foo']['_destroy'] = false_variable
481
 
      assert_no_difference('@pirate.send(@association_name).count') do
482
 
        @pirate.update_attributes(@alternate_params)
483
 
      end
484
 
    end
485
 
  end
486
 
 
487
 
  def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
488
 
    assert_no_difference('@pirate.send(@association_name).count') do
489
 
      @pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_destroy' => true }))
490
 
    end
491
 
    assert_difference('@pirate.send(@association_name).count', -1) { @pirate.save }
492
 
  end
493
 
 
494
 
  def test_should_automatically_enable_autosave_on_the_association
495
 
    assert Pirate.reflect_on_association(@association_name).options[:autosave]
496
 
  end
497
 
 
498
 
  private
499
 
 
500
 
  def association_setter
501
 
    @association_setter ||= "#{@association_name}_attributes=".to_sym
502
 
  end
503
 
 
504
 
  def association_getter
505
 
    @association_getter ||= "#{@association_name}_attributes".to_sym
506
 
  end
507
 
end
508
 
 
509
 
class TestNestedAttributesOnAHasManyAssociation < ActiveRecord::TestCase
510
 
  def setup
511
 
    @association_type = :has_many
512
 
    @association_name = :birds
513
 
 
514
 
    @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
515
 
    @pirate.birds.create!(:name => 'Posideons Killer')
516
 
    @pirate.birds.create!(:name => 'Killer bandita Dionne')
517
 
 
518
 
    @child_1, @child_2 = @pirate.birds
519
 
 
520
 
    @alternate_params = {
521
 
      :birds_attributes => {
522
 
        'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
523
 
        'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
524
 
      }
525
 
    }
526
 
  end
527
 
 
528
 
  include NestedAttributesOnACollectionAssociationTests
529
 
end
530
 
 
531
 
class TestNestedAttributesOnAHasAndBelongsToManyAssociation < ActiveRecord::TestCase
532
 
  def setup
533
 
    @association_type = :has_and_belongs_to_many
534
 
    @association_name = :parrots
535
 
 
536
 
    @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
537
 
    @pirate.parrots.create!(:name => 'Posideons Killer')
538
 
    @pirate.parrots.create!(:name => 'Killer bandita Dionne')
539
 
 
540
 
    @child_1, @child_2 = @pirate.parrots
541
 
 
542
 
    @alternate_params = {
543
 
      :parrots_attributes => {
544
 
        'foo' => { :id => @child_1.id, :name => 'Grace OMalley' },
545
 
        'bar' => { :id => @child_2.id, :name => 'Privateers Greed' }
546
 
      }
547
 
    }
548
 
  end
549
 
 
550
 
  include NestedAttributesOnACollectionAssociationTests
551
 
end
552
 
 
553
 
class TestNestedAttributesLimit < ActiveRecord::TestCase
554
 
  def setup
555
 
    Pirate.accepts_nested_attributes_for :parrots, :limit => 2
556
 
 
557
 
    @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
558
 
  end
559
 
 
560
 
  def teardown
561
 
    Pirate.accepts_nested_attributes_for :parrots, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
562
 
  end
563
 
 
564
 
  def test_limit_with_less_records
565
 
    @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Big Big Love' } } }
566
 
    assert_difference('Parrot.count') { @pirate.save! }
567
 
  end
568
 
 
569
 
  def test_limit_with_number_exact_records
570
 
    @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' }, 'bar' => { :name => 'Blown Away' } } }
571
 
    assert_difference('Parrot.count', 2) { @pirate.save! }
572
 
  end
573
 
 
574
 
  def test_limit_with_exceeding_records
575
 
    assert_raises(ActiveRecord::NestedAttributes::TooManyRecords) do
576
 
      @pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' },
577
 
                                                      'bar' => { :name => 'Blown Away' },
578
 
                                                      'car' => { :name => 'The Happening' }} }
579
 
    end
580
 
  end
581
 
end