diff options
Diffstat (limited to 'activerecord/lib/active_record/nested_attributes.rb')
-rw-r--r-- | activerecord/lib/active_record/nested_attributes.rb | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 602ab9e2f4..d607f49e2b 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -90,8 +90,9 @@ module ActiveRecord # accepts_nested_attributes_for :posts # end # - # You can now set or update attributes on an associated post model through - # the attribute hash. + # You can now set or update attributes on the associated posts through + # an attribute hash for a member: include the key +:posts_attributes+ + # with an array of hashes of post attributes as a value. # # For each hash that does _not_ have an <tt>id</tt> key a new record will # be instantiated, unless the hash also contains a <tt>_destroy</tt> key @@ -114,10 +115,10 @@ module ActiveRecord # hashes if they fail to pass your criteria. For example, the previous # example could be rewritten as: # - # class Member < ActiveRecord::Base - # has_many :posts - # accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? } - # end + # class Member < ActiveRecord::Base + # has_many :posts + # accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? } + # end # # params = { member: { # name: 'joe', posts_attributes: [ @@ -134,19 +135,19 @@ module ActiveRecord # # Alternatively, :reject_if also accepts a symbol for using methods: # - # class Member < ActiveRecord::Base - # has_many :posts - # accepts_nested_attributes_for :posts, reject_if: :new_record? - # end + # class Member < ActiveRecord::Base + # has_many :posts + # accepts_nested_attributes_for :posts, reject_if: :new_record? + # end # - # class Member < ActiveRecord::Base - # has_many :posts - # accepts_nested_attributes_for :posts, reject_if: :reject_posts + # class Member < ActiveRecord::Base + # has_many :posts + # accepts_nested_attributes_for :posts, reject_if: :reject_posts # - # def reject_posts(attributed) - # attributed['title'].blank? - # end - # end + # def reject_posts(attributed) + # attributed['title'].blank? + # end + # end # # If the hash contains an <tt>id</tt> key that matches an already # associated record, the matching record will be modified: @@ -183,6 +184,29 @@ module ActiveRecord # member.save # member.reload.posts.length # => 1 # + # Nested attributes for an associated collection can also be passed in + # the form of a hash of hashes instead of an array of hashes: + # + # Member.create(name: 'joe', + # posts_attributes: { first: { title: 'Foo' }, + # second: { title: 'Bar' } }) + # + # has the same effect as + # + # Member.create(name: 'joe', + # posts_attributes: [ { title: 'Foo' }, + # { title: 'Bar' } ]) + # + # The keys of the hash which is the value for +:posts_attributes+ are + # ignored in this case. + # However, it is not allowed to use +'id'+ or +:id+ for one of + # such keys, otherwise the hash will be wrapped in an array and + # interpreted as an attribute hash for a single post. + # + # Passing attributes for an associated collection in the form of a hash + # of hashes can be used with hashes generated from HTTP/HTML parameters, + # where there maybe no natural way to submit an array of hashes. + # # === Saving # # All changes to models, including the destruction of those marked for @@ -338,7 +362,7 @@ module ActiveRecord assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes) elsif attributes['id'].present? - raise_nested_attributes_record_not_found(association_name, attributes['id']) + raise_nested_attributes_record_not_found!(association_name, attributes['id']) elsif !reject_new_record?(association_name, attributes) method = "build_#{association_name}" @@ -428,7 +452,7 @@ module ActiveRecord assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) end else - raise_nested_attributes_record_not_found(association_name, attributes['id']) + raise_nested_attributes_record_not_found!(association_name, attributes['id']) end end end @@ -490,7 +514,7 @@ module ActiveRecord end end - def raise_nested_attributes_record_not_found(association_name, record_id) + def raise_nested_attributes_record_not_found!(association_name, record_id) raise RecordNotFound, "Couldn't find #{self.class.reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" end end |