If you’ve ever needed to handle complex object relationships with a single form, accepts_nested_attributes
might be exactly what you’re looking for.
accepts_nested_attributes
creates an attribute on the host object that, by default, handles mass assignment for a guest object.
For example, if a User
class has a Profile
via a has_one
relationship, adding accepts_nested_attributes_for :profile
to the User
class with create a profile_attributes=
method. At its core, this method looks like:
def profile_attributes=(values)
profile.assign_attributes(values)
end
Of course, Rails adds its magic, but this is the general idea.
When building forms, fields_for
helps structure nested data automatically:
<%= form_with model: user do |form| %>
<%= form.fields_for :profile_attributes do |profile_form| %>
<%= profile_form.text_field :name %>
<!-- Generates: <input name="user[profile_attributes][name]" /> -->
<% end %>
<% end %>
This ensures your form inputs map directly to nested attributes in your models.
In your controller, update the params to allow nested attributes:
class UsersController < ApplicationController
def update
user.assign_attributes(user_params)
end
def user_params
params.require(:user).permit(:stuff, profile_attributes: [:name, :description])
end
end
And there you have it! With a few lines of code, accepts_nested_attributes
helps you build intuitive forms for complex relationships.
Come back tomorrow for common pitfalls and how to avoid them!