Problem
Two view models inherit from EffortWithLapSplitRows for implementation reuse (the lap_split_rows machinery, related_split_times, method_missing delegation to the effort) while deliberately refusing the parent's construction protocol, each carrying an inline Lint/MissingSuper disable:
app/view_models/plan_display.rb:12 — built from a course and params; there is no persisted effort, so the parent's post_initialize → validate_setup (raises without an effort) → load_effort (re-queries via ranking_subquery) is inapplicable. Its "effort" is a new unsaved record whose split times come from the projection engine.
app/view_models/effort_place_view.rb:7 — takes an effort but assigns effort.with_rank directly, skipping the parent's load_effort reload and validate_setup.
Calling super in either would raise or run a meaningless query, so the omissions are intentional — but the cop is pointing at a real smell: these are not is-a relationships. A pacing plan is not an effort-with-rows; it borrows the row-building.
Proposal
Extract the shared machinery (lap_split_rows / rows_from_lap_splits, related_split_times, ordered/indexed split time helpers, effort delegation) into a module (or compose an instance) that EffortWithLapSplitRows, PlanDisplay, and EffortPlaceView all use. Each class then owns an honest constructor, and both rubocop:disable Lint/MissingSuper annotations go away.
Worth checking while in there: EffortAnalysisView also subclasses EffortWithLapSplitRows with its own load_effort override — it may want the same treatment for consistency, even though it currently participates in the parent's constructor.
Noticed while implementing #2229 (see discussion on the PlanDisplay changes in #2231); deliberately kept out of that PR's scope.
🤖 Generated with Claude Code
Problem
Two view models inherit from
EffortWithLapSplitRowsfor implementation reuse (thelap_split_rowsmachinery,related_split_times,method_missingdelegation to the effort) while deliberately refusing the parent's construction protocol, each carrying an inlineLint/MissingSuperdisable:app/view_models/plan_display.rb:12— built from acourseandparams; there is no persisted effort, so the parent'spost_initialize→validate_setup(raises without an effort) →load_effort(re-queries viaranking_subquery) is inapplicable. Its "effort" is a new unsaved record whose split times come from the projection engine.app/view_models/effort_place_view.rb:7— takes an effort but assignseffort.with_rankdirectly, skipping the parent'sload_effortreload andvalidate_setup.Calling
superin either would raise or run a meaningless query, so the omissions are intentional — but the cop is pointing at a real smell: these are not is-a relationships. A pacing plan is not an effort-with-rows; it borrows the row-building.Proposal
Extract the shared machinery (
lap_split_rows/rows_from_lap_splits,related_split_times, ordered/indexed split time helpers, effort delegation) into a module (or compose an instance) thatEffortWithLapSplitRows,PlanDisplay, andEffortPlaceViewall use. Each class then owns an honest constructor, and bothrubocop:disable Lint/MissingSuperannotations go away.Worth checking while in there:
EffortAnalysisViewalso subclassesEffortWithLapSplitRowswith its ownload_effortoverride — it may want the same treatment for consistency, even though it currently participates in the parent's constructor.Noticed while implementing #2229 (see discussion on the
PlanDisplaychanges in #2231); deliberately kept out of that PR's scope.🤖 Generated with Claude Code