skills/dynamic-nested-attributes/SKILL.md
Implement Rails nested attributes with dynamic add/remove functionality using Turbo Streams and Simple Form. Use when building forms where users need to manage multiple child records (has_many associations), add/remove nested items without page refresh, or create bulk records inline.
npx skillsauth add rolemodel/rolemodel-skills dynamic-nested-attributesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Implement Rails nested attributes with dynamic add/remove functionality using Turbo Streams and Simple Form. This pattern allows users to add and remove associated records inline within a parent form.
accepts_nested_attributes_for :association_name in the model or form objectCreate a form that includes:
simple_fields_for for rendering existing nested items#accessories)Example:
= simple_form_for resource do |f|
= f.simple_fields_for :items do |ff|
= render 'item_fields', f: ff, resource:
= render 'add_button', index: resource.items.size
Add Button Partial (_add_button.html.slim):
-# locals: (index:)
= link_to icon('add'), new_parent_item_path(index: index),
id: 'add_button', class: 'btn', data: { turbo_stream: true }
Create a partial (e.g., _item_fields.html.slim) that:
Example:
fieldset id="item_#{f.index}" controller='destroy-nested-attributes'
= f.hidden_field :_destroy, data: { destroy_nested_attributes_target: 'input' }
= f.input :name
= f.input :quantity
.form-row__actions
= button_tag icon('delete'), type: 'button', class: 'btn btn-delete',
data: { action: 'destroy-nested-attributes#perform' }
Implement a new action that:
index parameter for tracking positionExample:
def new
@item = Item.new
end
Create a new.turbo_stream.slim view that:
index parameter to ensure unique field namesExample:
= turbo_stream.replace 'add_button', partial: 'add_button', locals: { index: params[:index].to_i + 1 }
= simple_form_for :parent, url: '' do |f|
= f.simple_fields_for :items_attributes, @item, index: params[:index] do |ff|
= turbo_stream.append 'items', partial: 'item_fields', locals: { f: ff }
Create a Stimulus controller to handle client-side removal:
Example JavaScript:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ['input']
static classes = ['destroyed']
connect() {
if (!this.hasDestroyedClass) {
this.element.setAttribute(`data-${this.identifier}-destroyed-class`, 'is-hidden')
}
}
perform() {
this.inputTarget.value = '1'
this.element.classList.add(this.destroyedClass)
}
}
accepts_nested_attributes_for to model/form objectsimple_fields_for and container elementnew action with index supportPass filtered collections to nested partials:
= render 'item_fields', f: ff, resource:, collection: resource.items
If there is not an existing new route in use, use the following pattern
resources :items, only: [:new]
If one does exist, create a new namespaced controller
namespace :parent do
resources :items, only: [:new]
end
def item_params
params.require(:parent).permit(
:category,
:subcategory,
items_attributes: %i[
name
quantity
part_id
optional
hidden
]
)
end
testing
Verify what Ruby versions actually exist and install a specific Ruby via rbenv. Use BEFORE asserting that any Ruby version does or doesn't exist (e.g., "Ruby 4.0 isn't out yet", "the latest Ruby is 3.x", "Ruby X.Y.Z doesn't exist"). Also use when the user asks "what's the latest Ruby", "is Ruby X out", "does Ruby X.Y exist", "install Ruby", "switch to Ruby X", "what Ruby is installed", or mentions a specific Ruby version you're unsure about. Claude's training data may be out of date — run `check.sh` first.
development
Trace code through the stack — upward to entry points, downward to data, or laterally across boundaries. Use when the user asks "where does this get called from", "what calls this method", "trace this through the stack", "how does this request flow", "where does this data come from", "follow this through the code", or pastes/selects a piece of code and wants to understand where it fits in the larger system.
tools
Pick the single highest-priority unresolved Sentry issue and hand it off to a fixer skill. Use when triaging Sentry errors, running automated issue triage, or when asked to fix the top Sentry issue in a project.
tools
Find and fix issues from Sentry using MCP. Use when asked to fix Sentry errors, debug production issues, investigate exceptions, or resolve bugs reported in Sentry. Methodically analyzes stack traces, breadcrumbs, traces, and context to identify root causes.