Skip to content

Alternative: RepeatingWithin cycle kind (I notation) — subclasses Within#72

Closed
rymiwe wants to merge 1 commit intomainfrom
feat/repeating-within-cycle-kind
Closed

Alternative: RepeatingWithin cycle kind (I notation) — subclasses Within#72
rymiwe wants to merge 1 commit intomainfrom
feat/repeating-within-cycle-kind

Conversation

@rymiwe
Copy link
Contributor

@rymiwe rymiwe commented Mar 18, 2026

Summary

Alternative to #71 — same behavior, different class structure. This PR subclasses Within to make the relationship explicit, per jdowd's feedback on #69.

V1I24MF2026-03-31 = complete 1 every 24 months from March 31, 2026. After satisfaction, the consuming app calls reactivated_notation(completion_date) to start the next window.

Design: Subclass vs Sibling

#71 (Interval < Cycle) This PR (RepeatingWithin < Within)
Relationship to Within Implicit (same implementation) Explicit (inheritance)
Inherited from Within Nothing final_date, start_date, date_range
Overrides N/A (standalone) recurring?, to_s, extend_period, last_completed, expiration_of, satisfied_by?, start_date (nil-safe), final_date (nil-safe)
Liskov concern None recurring? returns opposite of parent
Developer signal "This is its own thing" "This is Within, but repeating"

Tradeoffs

Subclass (this PR):

  • Makes Within relationship immediately apparent to developers
  • Inherits final_date/start_date computation (DRY)
  • But overrides 7 methods including core semantics (recurring?, satisfied_by?)
  • Needs nil-safe overrides for start_date/final_date because Within assumes active state

Sibling (#71):

  • Clean separation, no Liskov concern
  • Self-contained — all behavior visible in one file
  • But duplicates final_date/start_date one-liners from Within
  • Relationship to Within only visible by reading both files

Bonus: reactivated_notation alias

Added reactivated_notation(date) as an alias for activated_notation(date). Same operation, but self-documenting at the call site:

# Activating a dormant cycle
notation = dormant_cycle.activated_notation(first_date)

# Re-anchoring a satisfied RepeatingWithin
notation = satisfied_cycle.reactivated_notation(completion_date)

Test plan

  • All 209 gem specs pass (179 existing + 29 RepeatingWithin + 1 dormant coverage)
  • Spec verifies RepeatingWithin < Within inheritance
  • Spec verifies final_date/start_date match Within's computation
  • StandardRB clean

Addresses QUAL-6317
Alternative to #71
Depends on #70 (EndOf fix)

Alternative to #71 (Interval) — same behavior, different class structure.
RepeatingWithin subclasses Within to make the relationship explicit.

V1I24MF2026-03-31 = complete 1 every 24 months from March 31, 2026.
After satisfaction, consuming app calls reactivated_notation(date) to
start the next window.

Overrides from Within:
- recurring? → true (Within is false)
- to_s → "every...from" format (Within uses "within...range")
- extend_period → no-op (re-anchors instead of extending)
- last_completed → returns from_date (current window anchor)
- expiration_of → returns final_date
- satisfied_by? → checks anchor <= final_date
- start_date/final_date → nil-safe for dormant state

Also adds reactivated_notation(date) alias for activated_notation to
make the re-anchoring call site self-documenting.
@rymiwe rymiwe closed this Mar 20, 2026
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.

1 participant