Skip to content

Engine: Key a collection whose rows are built by a tag helper - #2271

Merged
marcoroth merged 3 commits into
slots/clifrom
slots/keying
Aug 18, 2026
Merged

Engine: Key a collection whose rows are built by a tag helper#2271
marcoroth merged 3 commits into
slots/clifrom
slots/keying

Conversation

@marcoroth

@marcoroth marcoroth commented Aug 18, 2026

Copy link
Copy Markdown
Owner

This pull request fixes a collection losing its keying when its rows are built by a tag helper.

<%= tag.li id: person[:id] do %>

produces the same HTML as <li id="...">, but the collection fell back to index keying and emitted no row markers at all, so nothing about that collection could be updated a row at a time.

Parsed with action_view_helpers, a tag helper is already an element whose open tag is ERB and whose keyword arguments are real attributes, so the key is there to be read:

@ HTMLElementNode
    @ ERBOpenTagNode
        @ HTMLAttributeNode
            @ HTMLAttributeNameNode -> LiteralNode "id"
            @ HTMLAttributeValueNode -> RubyLiteralNode "person[:id]"

SlotVisitor refused to read it in two places. attributes_for bailed unless the open tag was an HTMLOpenTagNode, so it found no attributes on a helper's element, and key_parts_for knew about ERBContentNode and LiteralNode but not RubyLiteralNode, which is what a keyword argument holds where a written attribute holds ERB.

That parse is also what stops a helper taking a block from being marked as a block with markers inside it, which is a slot whose value is used, so action_view_helpers is a required parser option here and not a recommended one.

@github-actions github-actions Bot added ruby Ruby source for the gem and its libraries rbs RBS type signatures in sig/ engine Herb engine and Rails template compilation rubygem The herb RubyGem and its packaging labels Aug 18, 2026
@marcoroth marcoroth added the reactivity Reactive ERB templates: diff and re-render only what changed label Aug 18, 2026
@nx-cloud

nx-cloud Bot commented Aug 18, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 9483ba6

Command Status Duration Result
nx run-many -t test --all --parallel --exclude=... ✅ Succeeded 3m 39s View ↗
nx run-many -t build --all --exclude=herb-langu... ✅ Succeeded 15s View ↗
nx build @herb-tools/tailwind-class-sorter ✅ Succeeded 1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-18 03:13:14 UTC

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

🌿 Interactive Playground and Documentation Preview

A preview deployment has been built for this pull request. Try out the changes live in the interactive playground:


🌱 Grown from commit 9483ba6


✅ Preview deployment has been cleaned up.

@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown
npx https://pkg.pr.new/@herb-tools/formatter@2271
npx https://pkg.pr.new/@herb-tools/language-server@2271
npx https://pkg.pr.new/@herb-tools/linter@2271

commit: 9483ba6

@marcoroth marcoroth added the client-runtime Browser runtime for the Herb slots. label Aug 18, 2026
`<%= tag.li id: person[:id] do %>` produces the same HTML as `<li id="...">` but lost keying
entirely, so the collection fell back to index keying and emitted no row markers at all.

Parsed with `action_view_helpers`, a tag helper is already an element whose open tag is ERB and
whose keyword arguments are real attributes, so the key is there to be read:

    HTMLElementNode
      ERBOpenTagNode
        HTMLAttributeNode
          HTMLAttributeNameNode -> LiteralNode "id"
          HTMLAttributeValueNode -> RubyLiteralNode "person[:id]"

`SlotVisitor` refused to read it in two places. `attributes_for` bailed unless the open tag was an
`HTMLOpenTagNode`, so it found no attributes on a helper's element, and `key_parts_for` knew about
`ERBContentNode` and `LiteralNode` but not `RubyLiteralNode`, which is what a keyword argument
holds where a written attribute holds ERB.

That parse is also what stops a helper taking a block from being marked as a block with markers
inside it, which is a slot whose value is used, so the option is required rather than recommended.

(cherry picked from commit d4689eee5f54c4b14e73beee97e77a834622d376)
(cherry picked from commit 3ca7fa0)
@marcoroth
marcoroth merged commit d4cf287 into main Aug 18, 2026
64 of 67 checks passed
@marcoroth
marcoroth deleted the slots/keying branch August 18, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client-runtime Browser runtime for the Herb slots. engine Herb engine and Rails template compilation rbs RBS type signatures in sig/ reactivity Reactive ERB templates: diff and re-render only what changed ruby Ruby source for the gem and its libraries rubygem The herb RubyGem and its packaging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant