我开始对所有模型的 ID 字段使用 Postgres UUID 类型。工作得很好并且在 Rails 4 中得到支持(大部分):
create_table :users, id: :uuid do |t|
# ...
end
问题是,如果您尝试查找 id 为 X 的行,但 X 不是格式正确的 UUID 字符串,Postgres 将引发错误。
> 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。不再存在。
我怎样才能以 DRY 方式避免这种情况?我不能只拯救 PG::InvalidTextRepresentation
并渲染 404,因为 other things也可能导致此错误。
更新
我认为 ID 参数格式的正则表达式是干净的,如果不匹配它会引发 404:
resources :users, id: /uuid-regex-here/
但我仍然有保持干燥的问题;我不想把它放在我 route 的每一个资源上。我可以在一个语句中声明多个资源,但前提是没有像成员操作那样的其他选项。 所以也许更好的问题是:有没有办法为所有路由设置 id 正则表达式?
最佳答案
您可以通过 constraints() do ... end
一次向多个路由添加路由约束。
我最终这样做并在所有 :id
参数上设置了全局约束以将其与 UUID 正则表达式匹配:
MyApp::Application.routes.draw do
constraints(id: /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i) do
# my routes here
end
end
这样,/posts/123 或/posts/foobar 在调用 Controller 操作之前不再匹配/posts/:id 和 404,从而避免了 PG 类型错误。
我所有的模型都将使用 UUID 作为他们的 ID,所以这是干净和干燥的。如果我也有一些带有整数 ID 的模型,它会变得不那么干净。
关于ruby-on-rails - 在 Rails 中使用 Postgres UUID 时避免 PG::InvalidTextRepresentation 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21338873/