@@ -269,23 +269,36 @@ def accepts_nested_attributes_for(*attr_names)
269
269
self . nested_attributes_options = nested_attributes_options
270
270
271
271
type = ( reflection . collection? ? :collection : :one_to_one )
272
-
273
- # def pirate_attributes=(attributes)
274
- # assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
275
- # end
276
- generated_feature_methods . module_eval <<-eoruby , __FILE__ , __LINE__ + 1
277
- if method_defined?(:#{ association_name } _attributes=)
278
- remove_method(:#{ association_name } _attributes=)
279
- end
280
- def #{ association_name } _attributes=(attributes)
281
- assign_nested_attributes_for_#{ type } _association(:#{ association_name } , attributes)
282
- end
283
- eoruby
272
+ generate_association_writer ( association_name , type )
284
273
else
285
274
raise ArgumentError , "No association found for name `#{ association_name } '. Has it been defined yet?"
286
275
end
287
276
end
288
277
end
278
+
279
+ private
280
+
281
+ # Generates a writer method for this association. Serves as a point for
282
+ # accessing the objects in the association. For example, this method
283
+ # could generate the following:
284
+ #
285
+ # def pirate_attributes=(attributes)
286
+ # assign_nested_attributes_for_one_to_one_association(:pirate, attributes)
287
+ # end
288
+ #
289
+ # This redirects the attempts to write objects in an association through
290
+ # the helper methods defined below. Makes it seem like the nested
291
+ # associations are just regular associations.
292
+ def generate_association_writer ( association_name , type )
293
+ generated_feature_methods . module_eval <<-eoruby , __FILE__ , __LINE__ + 1
294
+ if method_defined?(:#{ association_name } _attributes=)
295
+ remove_method(:#{ association_name } _attributes=)
296
+ end
297
+ def #{ association_name } _attributes=(attributes)
298
+ assign_nested_attributes_for_#{ type } _association(:#{ association_name } , attributes)
299
+ end
300
+ eoruby
301
+ end
289
302
end
290
303
291
304
# Returns ActiveRecord::AutosaveAssociation::marked_for_destruction? It's
@@ -371,20 +384,7 @@ def assign_nested_attributes_for_collection_association(association_name, attrib
371
384
raise ArgumentError , "Hash or Array expected, got #{ attributes_collection . class . name } (#{ attributes_collection . inspect } )"
372
385
end
373
386
374
- if limit = options [ :limit ]
375
- limit = case limit
376
- when Symbol
377
- send ( limit )
378
- when Proc
379
- limit . call
380
- else
381
- limit
382
- end
383
-
384
- if limit && attributes_collection . size > limit
385
- raise TooManyRecords , "Maximum #{ limit } records are allowed. Got #{ attributes_collection . size } records instead."
386
- end
387
- end
387
+ check_record_limit! ( options [ :limit ] , attributes_collection )
388
388
389
389
if attributes_collection . is_a? Hash
390
390
keys = attributes_collection . keys
@@ -433,6 +433,29 @@ def assign_nested_attributes_for_collection_association(association_name, attrib
433
433
end
434
434
end
435
435
436
+ # Takes in a limit and checks if the attributes_collection has too many
437
+ # records. The method will take limits in the form of symbols, procs, and
438
+ # number-like objects (anything that can be compared with an integer).
439
+ #
440
+ # Will raise an TooManyRecords error if the attributes_collection is
441
+ # larger than the limit.
442
+ def check_record_limit! ( limit , attributes_collection )
443
+ if limit
444
+ limit = case limit
445
+ when Symbol
446
+ send ( limit )
447
+ when Proc
448
+ limit . call
449
+ else
450
+ limit
451
+ end
452
+
453
+ if limit && attributes_collection . size > limit
454
+ raise TooManyRecords , "Maximum #{ limit } records are allowed. Got #{ attributes_collection . size } records instead."
455
+ end
456
+ end
457
+ end
458
+
436
459
# Updates a record with the +attributes+ or marks it for destruction if
437
460
# +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
438
461
def assign_to_or_mark_for_destruction ( record , attributes , allow_destroy )
@@ -452,6 +475,11 @@ def reject_new_record?(association_name, attributes)
452
475
has_destroy_flag? ( attributes ) || call_reject_if ( association_name , attributes )
453
476
end
454
477
478
+ # Determines if a record with the particular +attributes+ should be
479
+ # rejected by calling the reject_if Symbol or Proc (if defined).
480
+ # The reject_if option is defined by +accepts_nested_attributes_for+.
481
+ #
482
+ # Returns false if there is a +destroy_flag+ on the attributes.
455
483
def call_reject_if ( association_name , attributes )
456
484
return false if has_destroy_flag? ( attributes )
457
485
case callback = self . nested_attributes_options [ association_name ] [ :reject_if ]
0 commit comments