Skip to content

docs(log_set): say that exercise_id is the movement performed - #19

Open
wromansky wants to merge 2 commits into
wger-project:masterfrom
wromansky:docs/log-set-exercise-id
Open

docs(log_set): say that exercise_id is the movement performed#19
wromansky wants to merge 2 commits into
wger-project:masterfrom
wromansky:docs/log-set-exercise-id

Conversation

@wromansky

@wromansky wromansky commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

log_set documents routine_id, slot_entry_id, iteration, reps_unit, the *_target fields, session_id and next_log_id. exercise_id is the one parameter it never mentions — and the ids paragraph tells the caller to "get all three from get_workout_for_date", which returns exercise_id and slot_entry_id together inside each planned entry.

So the only exercise ids a caller holds are the planned ones, and nothing says they may not be the right ones.

What goes wrong

Substituted work gets filed under the planned exercise. A machine is occupied, the trainee does the cable or rope version, and the set is written with the slot's planned exercise_id:

  • a rope pushdown stored as a machine pushdown
  • a cable lateral raise stored as a machine lateral raise

The measurements are correct and the movement is wrong, and no later reading of the log can tell the two apart. Two things break downstream:

  1. The planned exercise's history is polluted with loads from a different implement, so the next progression decision on it is anchored to a number that was never lifted on that machine.
  2. The substitute's own history stays empty, because its id was never written — so if that movement appears elsewhere in the routine, it reads as never performed.

wger accepts the correct call

Verified rather than assumed:

  • manager_workoutlog has no constraint tying exercise_id to slot_entry_id — they are separate foreign keys.
  • WorkoutLogSerializer (wger/manager/api/serializers.py) declares exercise and slot_entry as independent fields, with no validate() and no cross-field check.

So the substitute's exercise_id can be passed while routine_id, slot_entry_id and iteration still point at the planned slot. The set stays attached to the plan, and the history stays true to what was lifted. That combination was always available; nothing in the docstring said so.

The change

Docstring only, no behaviour change.

  • A new paragraph states that exercise_id is the movement actually performed, names the substitution case, and says to keep the plan ids pointing at the planned slot while passing the substitute's own id.
  • The ids paragraph now says out loud that get_workout_for_date's planned entries carry an exercise_id of their own, that it is the movement planned, and that it should be passed only when it is also the one performed. The old "get all three from get_workout_for_date" phrasing is what invited copying the whole bundle across.
  • Points at search_exercises for finding the substitute's id, since that call is the step a caller has no reason to make otherwise.

Tests

No new tests: the change is documentation and there is no behaviour to assert. Full suite unchanged at 247 passed. ruff check and ruff format --check clean on the touched file.

Note

#18 also edits the log_set docstring, in a different paragraph (reps_unit). Checked with git merge-tree: the hunks do not overlap and the two branches merge cleanly, so neither blocks the other.

log_set documents routine_id, slot_entry_id, iteration, reps_unit, the
*_target fields, session_id and next_log_id. exercise_id is the one
parameter the docstring never mentions, and the ids paragraph tells the
caller to "get all three from get_workout_for_date" — which returns
exercise_id and slot_entry_id together inside each planned entry.

The result is that the only exercise ids a caller holds are the planned
ones, and nothing says they may not be the right ones. Substituted work
gets filed under the planned exercise: a rope pushdown stored as a
machine pushdown, a cable lateral raise stored as a machine lateral
raise. The measurements are right and the movement is wrong, and no
later reading of the log can tell. The next prescription for the
substitute then sees no history at all, because its own id was never
written.

wger accepts the correct call. manager_workoutlog has no constraint
tying exercise_id to slot_entry_id, and WorkoutLogSerializer declares
exercise and slot_entry as independent fields with no cross-field
validation, so the substitute's exercise_id can be passed while
routine_id, slot_entry_id and iteration still point at the planned slot.
That keeps the set attached to the plan and the history honest.

Docstring only; no behaviour change.
The previous wording told callers to read exercise_id off the movement
performed and 'not off the planned entry they came from'. Read literally
that forbids the common case: with no substitution the planned entry's
exercise_id IS the movement performed, and a caller following the letter
would search for an id it already holds — an extra round trip per set,
and a near-neighbour match would reintroduce a milder form of the
mis-filing this paragraph exists to prevent.

Say instead that get_workout_for_date's planned entries carry an
exercise_id of their own, that it is the movement PLANNED, and that it
should be passed only when it is also the one performed. That names the
trap more explicitly than before while leaving the common path free.
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