Это, наверное, лучшее, что вы можете сделать. Вы можете перебирать пары в хэше, создавая строку по ходу. Но в этом случае промежуточная строка должна быть создана и удалена на каждом шаге.
Есть ли у вас сценарий использования, когда это узкое место в производительности? В общем, Ruby делает так много закулисной работы, что беспокоиться о временном массиве, как это, вероятно, не стоит. Если вы обеспокоены тем, что это может быть проблемой, рассмотрите возможность профилирования вашего кода по скорости и использованию памяти, часто результаты не соответствуют вашим ожиданиям.