Repository navigation
Engine: dispatch on the value when resolving a tag helper's implicit attribute - #2722
FrancescoK wants to merge 3 commits into
Conversation
|
CI caught a package I had not run: The rewriter reads the same resolved attribute as the compiler, so changing the resolution changes what the codemod writes into a template: <%= image_tag @post.cover_image %><img src="<%= (@post.cover_image).then { |value| value.is_a?(String) || value.is_a?(Symbol) ? image_path(value) : polymorphic_url(value) } %>" />That might be correct, but definitely unpleasant to read. The expectation it replaces was |
|
We hit #2715 with ReActionView slots on, and this fixes it for us. I tested it cherry-picked onto v0.11.1 (applies cleanly): every One small thing for a follow-up: Thanks! |
…attribute turbo_frame_tag and image_tag choose how to build their id and src from the value's class at render time. Resolving them into markup chose statically, from the shape of the argument, so a String id reached dom_id and raised on to_key, and an Active Storage blob reached image_path and resolved to "". The type does not have to be known at compile time. Both now emit the branch the helper itself performs, binding the argument once so an expression with side effects still evaluates a single time. A literal argument still folds to static markup, and a literal dom_id call is still passed through, so the cases the resolution exists for are unchanged.
The rewriter reads the same resolved attribute as the compiler, so its output moves with it. The expectations it held described the guess: an Active Storage source rewritten to image_path resolves to "", which is the bug this fixes, written into a template rather than into compiled output.
turbo_frame_tag only read its first argument, so `turbo_frame_tag record, "notes"`
rendered `post_1` instead of `notes_post_1`. Read every positional id and
emit the same dispatch the helper performs: literal ids join statically,
anything else becomes `ids.first.respond_to?(:to_key) || is_a?(Class)
? dom_id(*ids) : ids.join("_")`.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
df12c4e to
63c6ddb
Compare
|
Thanks for testing this, @mattboldt. I added the multi-id case to this PR, so |
Fixes #2715.
turbo_frame_tagandimage_tagchoose how to build their implicit attribute fromthe value's class, at render time:
Resolving them into markup chose statically, from the shape of the argument, so a local holding a String reached
dom_idand raisedNoMethodError: undefined method 'to_key' for an instance of String, and an Active Storage blob reachedimage_pathand resolved to"".The type does not have to be known at compile time. Both now emit the branch the helper itself performs:
The argument binds once through
then, so an expression with side effects or a query still evaluates a single time.What is unchanged
A literal argument still folds to static markup —
turbo_frame_tag "tray"stillcompiles to
<turbo-frame id="tray">with nothing left to evaluate — and a literaldom_id(...)call is still passed through. Only the arguments that previously got a guess now carry the branch, and those were calling the whole helper before the resolution existed.skip_wrapping_forinconfig/action_view_helpers/**.ymlis untouched. It still decides what can fold; it is no longer what decides correctness.Multiple ids
turbo_frame_tagjoins ordom_ids every positional id, not just the first, soturbo_frame_tag record, "notes"was dropping the prefix (reported by @mattboldt below). Literal ids now join at compile time (turbo_frame_tag "notes", :listgivesnotes_list). Anything else carries the same branch the helper performs, over all ids:Two engine tests cover it.
Tests
turbo_frame_tag with a string id held in a localis added to the engine tests,which render through Action View and compare. It fails without this change and the rendered output matches Rails with it:
Three existing snapshots move from the guess to the branch. Their subjects — a model and an instance variable — still resolve through
dom_idat render time, so the behaviour they describe is unchanged.rake testpasses (5203 runs, 13718 assertions, 0 failures)