hqt
hqt

Reputation: 30284

Rails: accepts_nested_attributes_for explanation

I'm using Mongoid and rails_admin gem for my rails application. Here is my two model files:

Model Category

class Category
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name, type: String

  embeds_many :tags
  # accepts_nested_attributes_for :tags  # this line will be added later
end

Model Tag

class Tag
  include Mongoid::Document
  field :name, type: String

  embedded_in :category
end

When I run admin page (generated by rails_admin), I meet exception. In this exception, there is a message tell me that I should put accepts_nested_attributes_for :tag in Category model. After I put that line, no error appears.

So, my question is: Please explain for me purpose of accepts_nested_attributes_for. I see many tutorials, often those two lines use together:

   embeds_many :tags
  accepts_nested_attributes_for :tags

So why ? Why not only one line ?

@Edit: I also read this link. But I still not understand so much. explanation

Thanks :)

Upvotes: 0

Views: 1305

Answers (1)

pshoukry
pshoukry

Reputation: 765

From the docs

Nested attributes allow you to save attributes on associated records through the parent. By default nested attribute updating is turned off and you can enable it using the #accepts_nested_attributes_for class method. When you enable nested attributes an attribute writer is defined on the model.

In other words accepts nested attributes allows you to save the tags directly from the category model ( that's rails)

The embeds_many on the other hand is to add the relation between the category and tag (that's mongoid). it would still be valid without #accepts_nested_attributes but won't allow you to save both in one step from the parent.

A good example to this:

Enabling nested attributes on a one-to-one association allows you to create the member and avatar in one go:

params = { member: { name: 'Jack', avatar_attributes: { icon: 'smiling' } } } 
# both member and avatar passed in one hash
member = Member.create(params[:member])
member.avatar.id # => 2
member.avatar.icon # => 'smiling'

A very nice video to further explain the concept can be found here

Upvotes: 1

Related Questions