Back to Blog

Rails 7 adds accepts_nested_attributes_for support for delegated_type

on November 23, 2021
This blog is part of our Rails 7 series.

Rails 6.1 introduced the delegated_type to Active Record which makes it easier for models to share responsibilities. Please see our blog to read more about delegated_type.

1class Entry < ApplicationRecord
2  # Schema
3  #  entryable_type, entryable_id, ...
4  delegated_type :entryable, types: %w[ Message Comment ]
5end
6
7class Message
8  # Schema
9  #  subject, ...
10end
11
12class Comment
13  # Schema
14    #  content, ...
15end

The accepts_nested_attributes_for option is very helpful while handling nested forms. We can easily create and update associated records by passing details along with main object parameters when the accepts_nested_attributes_for option is enabled.

Before

The accepts_nested_attributes_for option is not available for delegated_type, hence we can't use nested forms for associated objects configured via delegated_type.

Rails 7 onwards

Rails 7 adds accepts_nested_attributes_for support to delegated_type, which allows to create and update records easily without needing to write specific methods or logic.

1class Entry < ApplicationRecord
2  delegated_type :entryable, types: %w[ Message Comment ]
3  accepts_nested_attributes_for :entryable
4end
5
6params = {
7  entry: {
8    entryable_type: 'Message',
9    entryable_attributes: { subject: 'Delegated Type' }
10  }
11}
12
13message_entry = Entry.create(params[:entry])
14
15params = {
16  entry: {
17    entryable_type: 'Comment',
18    entryable_attributes: { content: 'Looks Cool!' }
19  }
20}
21
22comment_entry = Entry.create(params[:entry])

If we want to deal with more logic or validations while creating the entryable objects, we'll have to create a method specifically and do the logic there.

1class Entry < ApplicationRecord
2  def self.create_with_comment(content)
3    # Validation logic goes here
4    create! entryable: Comment.new(content: content)
5  end
6end

Please check out this pull request for more details.