I am trying to show that every finitely generated projective module $P$ over a Dedekind domain $D$ is a direct sum of (fractional) ideals. May's notes on Dedekind domains claim the result can be proven by induction as follows: if $P$ has rank $n$, let $Q$ be a rank $n-1$ submodule of $P$ (constructed for example by taking elements spanning a subspace of dimension $n-1$ in $P \otimes \text{Frac}(D)$), and consider the short exact sequence
$$0 \to Q \to P \to P/Q \to 0.$$
By tensoring with $\text{Frac}(D)$ we see that $P/Q$ has rank $1$, and here May's notes claim this implies that $P/Q$ is projective, which is the crucial part of the inductive step.
I don't see how this works. It seems like you need to show that you can choose $Q$ so that you can guarantee that $P/Q$ is torsion-free. Otherwise consider, for example, the inclusion
$$\mathbb{Z} \ni 1 \mapsto (0, 2) \in \mathbb{Z} \oplus \mathbb{Z}.$$
Here the quotient is rank $1$ but has torsion.
So is this a genuine hole in the proof and, if so, how can it be repaired?
As indicated in the comments, you should saturate $Q$ in $P$ first, i.e. replace it by the preimage of the torsion in $P/Q,$ so that (after changing $Q$ in this way) we get that $P/Q$ is torsion-free.
The basic fact you need is that the saturation is again f.g., but this will follows from the fact that the torsion in $Q/P$ is f.g., being a submodule of the f.g. module $P/Q$.
The process of saturation is a common one in these sorts of situations, where we are playing off the relationship between modules over $D$ and its fraction field, and we want to avoid torsion appearing on the integral level. One way to proceed, which is a bit cleaner than your construction of $Q$, is to choose $V$ of dim'n $n-1$ in $P\otimes Frac(D)$, and set $Q = P \cap V$. Then $Q$ is f.g. (being a submodule of $P$) and is of rank $n-1$ (it spans $V$), and is automatically saturated in $P$ (because $P/Q$ embeds into $P\otimes D/V,$ which is a $Frac(D)$ vector space, and hence torsion free). (The difference b/w your construction and mine is that you took $Q$ to be the span of some specific vectors, hence free, whereas I didn't try to pin down the structure of $Q$ so precisely; I let it be whatever it had to be to be saturated.)
This latter way of proceeding is especially useful in iterated contexts (like if you had a filtration on $P\otimes Frac(D)$, and you want to obtain an underlying filtration on $P$ by some $Q$'s which are saturated, and which induces the original filtration after extending scalars back to $Frac(D)$: just intersect the vector spaces in the filtration with $P$!).