Nested Forms with RAILS
Nested forms is a form within another form. It’s nice to not jump between the parent and child forms when creating both the parent and the child in the same form. In this example, I’m using Post as a parent and Tags as the child. A Post will have many Tags.
There is a cool method
accepts_nested_attributes_for from ActiveRecord that allows you to save attributes on associated records through the parent. This method gives you the attribute writer, in this case, we got the
tags_attributes=(attributes) writer method. You can add
allow_destroy: true so if the post is deleted, this tag will be deleted also.
1 2 3 4
form_for for the new Post. We want to make a nested form so that we can create a form for a new Tag also. To do this, we will use
fields_for to make a
text_field to enter a new tag. We will be making a
Tag.new in place for the new tag.
1 2 3 4 5 6 7 8
See how if you inspect element, this new tag text field is called
tags_attributes? This came from the cool method
accepts_nested_attributes_for in the Post model. This automatically gives you nested params
post[tags_attributes][name]. Although we did
fields_for :tags, it gives you
tags_attributes in the params for free. It is also  because this is the first tag we’re making, but you can certainly enter more tag inputs if you wish.
To allow this in our params, we will do add
tags_attributes with the name field.
1 2 3 4
As a reminder, we made post_params as a private method so that we can do mass assignment, and prevent a hacker from editing the params and changing something in our forms that we didn’t want to change.
Now this will allow us to get a nested hash in our params that’s part of Post.
1 2 3 4 5 6 7 8 9 10
Now that we got the params we want, we have to actually create the new tag.
Once the form is submitted, this will go to the def create method of the Post controller, because it is sending a post request to the server.
1 2 3 4
We will do Post.new and put in the post_params from our private method, and it will set its attributes to whatever we provided in the params.
It will ALSO set the :name to the newly created tag, and associate this tag to this particular post. This was made possible because of the
accepts_nested_attributes_for method in our Post model.
Great! Now we have the tag that we just created– mrkittycat.
That’s the gist of it. This allowed me to create a new tag and associate it with this post, without making separate forms. It comes in handy at times.
To read more about nested forms, here is some documentation about it from ApiDock