fixxxer, давай представим ситуацию, когда в рамках одной модели нужна транзакция.
Например, пересчет дерева. Ты станешь писать операции с деревом в самой модели ActiveRecord?
Я - нет. Классы AR, которые мапятся на записи базы, у меня делают только одно: маппинг на записи, и ничего больше - инкапсуляция.
Логика приложения - в сервисный слой / unit of work / domain model / ваша конфессия.
Расчет позиции в дереве при разложении на двумерную модель - это промежуточная логика между бизнесом и медиа.
Можно расширить класс маппинга и прописать в нем интерфейс работы с деревом, но я предпочитаю адаптер. В будущем, когда логика операции изменится и потребует участия нескольких таблиц, или таблица разложится на несколько, из адаптера/декоратора будет легче перейти к композиции или внедрить стратегию. Здесь можно обернуть сохранение в транзакцию.
Такой подход дает мне гибкость и полиморфизм. Когда я добавляю новые поля в таблицу, я просто перегенерирую класс мапинга, переношу валидаторы, и все работает дальше.
Когда я добавляю новые таблицы, я меняю сервисный слой где нужно, а старый код работает со старыми классами мапинга.
Если я сильно меняю структуру базы, старый класс маппинга может превратиться в декоратор.
У меня логика такая. Интересно послушать другие варианты.