Я начал использовать тип Postgres UUID для полей идентификатора всех моих моделей. Отлично работает и поддерживается (по большей части) в Rails 4:
create_table :users, id: :uuid do |t|
# ...
end
Проблема в том, что Postgres выдаст ошибку, если вы попытаетесь найти строку, где id равен X, но X не является правильно отформатированной строкой UUID.
> User.find "3ac093e2-3a5e-4744-b49f-117b032adc6c"
ActiveRecord::RecordNotFound # good, will cause a 404
> User.find "foobar"
PG::InvalidTextRepresentation: ERROR # bad, will cause a 500
Поэтому, если мой пользователь находится на странице, где UUID находится в URL-адресе, а затем попытается изменить UUID, он получит ошибку 500 вместо 404. Или, возможно, он получит ссылку на объект, который больше не существует.
Как я могу избежать этого сценария СУХИМ способом? Я не могу просто спасти PG::InvalidTextRepresentation
и отобразить 404, потому что другие вещи также может вызвать эту ошибку.
ОБНОВЛЕНИЕ
Я думаю, что регулярное выражение в формате параметра идентификатора чистое, и оно поднимает 404, если оно не совпадает:
resources :users, id: /uuid-regex-here/
Но у меня все еще есть проблема оставаться СУХИМ; Я не хочу помещать это на каждый ресурс в моих маршрутах. Я могу объявить несколько ресурсов в одном выражении, но только если нет других вариантов, таких как действия членов. Возможно, лучше задать вопрос: есть ли способ установить регулярное выражение id для всех маршрутов?
before_filter
для ваших контроллеров. - person mu is too short   schedule 25.01.2014Model.find
вызовет RecordNotFound, если запись не будет найдена по какой-либо причине (включая ошибку типа, такую какM.find('pancakes')
когда ПК является целым числом). В модели Rails добавление ограничений к маршрутам, вероятно, было бы правильным, фильтр — это быстрый хак. Rails изобилует невысказанными предположениями (попробуйте добавить маршрут, который содержит адрес электронной почты, и посмотрите, что произойдет), и когда вы отклоняетесь от общепринятого пути, он уходит в сторону. - person mu is too short   schedule 25.01.2014M.find(id)
вызоветActiveRecord::RecordNotFound
, еслиid
по какой-либо причине не идентифицирует запись, и это предположение ошибочно. Основная проблема заключается в том, что вы отклоняетесь от Единого Истинного Пути Rails и теперь расплачиваетесь за это. Я полагаю, вы могли бы попытаться установить обезьяний патчfind
, но это противно и не поможет вам ни с чем, что не вызываетfind
. - person mu is too short   schedule 25.01.2014find
. - person tybro0103   schedule 25.01.2014find
— не единственное, что может вызвать эту ошибку. Патч обезьяныfind
, если вы считаете, что это достаточно хорошо. - person mu is too short   schedule 25.01.2014