Исключения нужно вызывать с случае ошибок, когда программа дальше работать не может. Но и стоить помнить, что исключения в руби работают медленно, поэтому использовать их лучше реже. А для обработки ошибок использовать обычные условия (if, else, unless ...).
пользователь пытается добавить несуществующие компании
Это проверку нужно вынести в валидацию модели. Сделать свой кастомный метод.
update_with_companies будет генерировать исключение.
Здесь не нужно исключение. Метод update_with_companies должен работать так же, как и стандартный метод save. Возможно, если убрать проверку компаний в валидацию, от метода update_with_companies вообще можно будет отказаться.
Кстати что вы думаете по поводу передачи params_with_companies которое по сути params из контроллера в модель?
params возвращает хеш, нет ничего плохого в том, чтобы передавать в метод модели хеш. Только нужно добавить дополнительную проверку для данных, так как они передаются от пользователя.