> Ruby convention is to add a ! when methods directly modify the object they're called on
No, Ruby convention is to add a “!” when there is a “less safe” version of an operation, for which a “more safe” version exists without a “!”.
Mutating versions of methods where a nonmutating version also exists are one common example, but not the only one, and mutating methods without a nonmutating counterpart don't get “!”.