Ответ 1

Потому что так, как архитекторы намеревались найти (id), чтобы работать, как указано в RDoc:

Найти по id - это может быть конкретный идентификатор (1), список идентификаторов (1, 5, 6) или массив идентификаторов ([5, 6, 10]). Если для всех перечисленных идентификаторов не будет найдена запись, то RecordNotFound будет поднят.

Если вы не хотите, чтобы исключение было поднято, используйте find_by_id, который вернет nil, если он не сможет найти объект с указанным id. Тогда ваш пример будет User.find_by_id(1).

Ответ 2

В дополнение к пояснениям runako, на самом деле очень полезно иметь выбор: возникает ли исключение или нет. Я работаю над блочным приложением, и я хотел бы добавить поддержку для просмотра следующей или предыдущей записи в блоге. Мне удалось добавить два метода экземпляра в мою модель Post, которые просто возвращают nil при попытке получить предыдущую запись при просмотре первого сообщения или следующей записи при просмотре последнего сообщения:

def next
  Post.find_by_id(id + 1)
end

def previous
  Post.find_by_id(id - 1)
end

Это позволяет избежать моего вспомогательного кода, который условно генерирует ссылки Previous Post/Next Post из-за необходимости обрабатывать исключение RecordNotFound, что было бы плохо, потому что оно использовало бы исключение для потока управления.