Code & Clay – Notes to self. Mainly Ruby/Rails.

Nested attributes

Sometimes it’s desirable to update one model’s attributes through an associated parent. Say, I might provide a form that asks a user for their name and email address but the user’s name is stored in the users table and their email address is recorded in another.

Rails provides the accepts_nested_attributes_for macro.

class User < ApplicationRecord
    has_one :contact_information, dependent: :destroy, required: true
    accepts_nested_attributes_for :contact_information

This allows me to update a user’s contact information like so:

user.update_attributes( contact_information_attributes: {
    phone_number: '123',
    email_address: 'hey@you.com
})

Instead of the headache of multiple forms and multiple controllers, I can now nest the contact information fields within the user form.

<%= bootstrap_form_for(@user) do |f| %>
  <%= f.text_field :name, required: true, autocomplete: "name" %>
  # ...
  <%= f.fields_for :contact_information do |ff| %>
      <%= ff.text_field :email_address, %>
      # ...

Finally, I need to specify the associated model’s attributes as allowable parameters in the parent resource’s controller:

def strong_params
    params.require(:user).permit(
      :name,
      contact_information_attributes: %i[
        email_address
      ]
    )
end

If you really want to get to grips with Ruby development and gain a solid understanding of Object Oriented Design, I thoroughly recommend Sandi Metz's Practical Object Oriented Design in Ruby. It's the perfect introduction to OOP and pragmatic Ruby. You can buy it here.

“Meticulously pragmatic and exquisitely articulate, Practical Object Oriented Design in Ruby makes otherwise elusive knowledge available to an audience which desperately needs it. The prescriptions are appropriate both as rules for novices and as guidelines for experienced professionals.”

Katrina Owen, Creator, Exercism

Essential Reading: Learn Rails 6