我开始将Postgres UUID类型用于所有模型的ID字段。在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
因此,如果我的用户位于URL中包含UUID的页面上,然后他们尝试更改UUID,则将收到500错误而不是404错误。或者可能是获得到不再存在的对象的链接。
如何才能以DRY方式避免这种情况?我不能仅仅拯救
PG::InvalidTextRepresentation
并渲染404,因为other things也可能导致此错误。更新
我认为ID参数格式的正则表达式很干净,如果不匹配,则会引发404:
resources :users, id: /uuid-regex-here/
但是我仍然有保持干燥的问题。我不想将其放在 route 的每个资源上。我可以在一条语句中声明多个资源,但前提是不要像成员操作那样使用其他选项。 因此,也许更好的问题是:是否可以为所有路由设置id regex?
最佳答案
您可以通过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/