tyb*_*103 10 postgresql ruby-on-rails rails-postgresql ruby-on-rails-4 rails-activerecord
我开始使用Postgres UUID类型用于我所有模型的id字段.非常好用,并且在Rails 4中支持(大部分):
create_table :users, id: :uuid do |t|
# ...
end
Run Code Online (Sandbox Code Playgroud)
问题是,如果您尝试查找id为X的行,但Postgres将引发错误,但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
Run Code Online (Sandbox Code Playgroud)
因此,如果我的用户位于URL中UUID所在的页面上,然后他们尝试更改UUID,则会得到500错误而不是404.或者他们可能会获得一个不再存在的对象的链接.
我怎样才能以干燥的方式避免这种情况?我不能只是拯救PG::InvalidTextRepresentation和渲染404,因为其他东西也可能导致这个错误.
UPDATE
我认为ID参数格式的正则表达式是干净的,如果它不匹配则会引发404:
resources :users, id: /uuid-regex-here/
Run Code Online (Sandbox Code Playgroud)
但我仍然有待保持干燥的问题; 我不想把它放在我的路线中的每一个资源上.我可以在一个语句中声明多个资源,但前提是不要像成员操作那样使用其他选项.所以也许更好的问题是:有没有办法为所有路由设置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
Run Code Online (Sandbox Code Playgroud)
这样,/ posts/123或/ posts/foobar在调用控制器操作之前不再匹配/ posts /:id和404,从而避免了PG类型错误.
我的所有模型都将使用UUID作为其ID,因此这是干净且干燥的.如果我有一些带有整数ID的模型,它会更不干净.
| 归档时间: |
|
| 查看次数: |
5009 次 |
| 最近记录: |