Skip to content

templates: relationshipMasterDeleteRefused="false" is the cascade, not the refusal (#7144) - #7182

Merged
delchev merged 1 commit into
masterfrom
issue-7144-master-delete-refused-boolean
Sep 9, 2026
Merged

templates: relationshipMasterDeleteRefused="false" is the cascade, not the refusal (#7144)#7182
delchev merged 1 commit into
masterfrom
issue-7144-master-delete-refused-boolean

Conversation

@delchev

@delchev delchev commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

CompositionChildren read the composition child's relationshipMasterDeleteRefused flag through ModelValues.truthy, which any non-empty string satisfies — so an .edm carrying the attribute spelled out as "false" generated exactly the REFUSE behavior it is asking not to have: the master's delete rejected while children exist, instead of the cascade.

The intent generator only ever emits the attribute when the refusal holds (EdmIntentGenerator writes the literal "true", and omits the key otherwise), so this could only bite the hand-authored / tool-produced path #7100 explicitly supports — the reverse index is derived from masterEntity/masterEntityId, precisely so a hand-authored .edm gets the cascade too.

ModelValues.bool parses the value instead of testing for presence: only true, in any case, is true; anything else — an absent key included — is false, which is the cascade the absent attribute already meant. truthy is untouched, since JavaScript truthiness is the right reading everywhere else in the parameter graph (widget lengths, free-text fields); this one attribute is a boolean an author can write out in full.

Nothing an intent Generate produces changes.

Tests

CompositionChildrenTest (module suite green, 6 tests in that class): a written-out "false" / "FALSE" is the cascade, and a "True" is still the refusal.

Fixes #7144

…t the refusal (#7144)

CompositionChildren read the flag through ModelValues.truthy, which any
non-empty string satisfies - so an .edm spelling the attribute out as
"false" generated the refusal it is asking not to have. The intent
generator only ever emits the attribute when it holds, so this could only
bite the hand-authored path #7100 explicitly supports (the reverse index
is derived, so a hand-authored .edm gets the cascade too).

ModelValues.bool parses the value instead: only true, in any case, is
true; anything else, an absent key included, is false - the cascade the
absent attribute already meant.

Fixes #7144

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@delchev
delchev force-pushed the issue-7144-master-delete-refused-boolean branch from 3f270ba to c0501a8 Compare September 8, 2026 21:08
@delchev
delchev merged commit 550a2d3 into master Sep 9, 2026
10 checks passed
@delchev
delchev deleted the issue-7144-master-delete-refused-boolean branch September 9, 2026 06:20
delchev pushed a commit that referenced this pull request Sep 10, 2026
…g obeys one rule (#7231) (#7273)

#7182 (#7144) fixed CompositionChildren.refusesMasterDelete misreading
relationshipMasterDeleteRefused="false" as true by adding a new helper,
ModelValues.bool - but ModelValues.isTrue already existed for exactly this ("the
model persists its flags as strings") and is what every other flag is read
through (dataUnique, isRequiredProperty, widgetIsMajor, detailCalendar, ...).
The result was two helpers for "is this string flag true": relationshipMaster-
DeleteRefused honoured "TRUE" / " true " while isRequiredProperty="TRUE" stayed
false. bool had exactly one caller.

Case-insensitive parsing is the wanted behaviour here - #7182 deliberately locked
it with tests (CompositionChildrenTest.aWrittenOutTrueIsTheRefusal /
aWrittenOutFalseIsTheCascade) because the flag guards a destructive cascade, so a
hand-authored "True" must refuse, not silently delete the children. So this makes
isTrue the single robust reader rather than dropping to a presence/lowercase test:

- ModelValues.isTrue now parses the value (Boolean.parseBoolean, trimmed, any
  case) - the exact body bool had - so every .edm flag is read the same way.
- ModelValues.bool is deleted; CompositionChildren routes through isTrue.
- New ModelValuesTest pins the single rule directly at the helper (lowercase/
  uppercase/padded true, written-out false in any case, absent key/map, Boolean).

The change is lenient-only for the other flags (the modeler always emits lowercase
"true"/"false"), so generated output is byte-identical.

Verified: mvn formatter:validate (BUILD SUCCESS, cache wiped); ide-template unit
suite green (125 tests, incl. new ModelValuesTest and the unchanged
CompositionChildrenTest); ModelGenerationIT green (1/1).

Fixes #7231

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ide-template: relationshipMasterDeleteRefused="false" in a hand-authored .edm is read as refuse

1 participant