ruby-on-rails - 在 Rails 中使用 Postgres UUID 时避免 PG::InvalidTextRepresentation 错误

标签 ruby-on-rails postgresql ruby-on-rails-4 rails-activerecord rails-postgresql

我开始对所有模型的 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/

相关文章:

ruby-on-rails - 可以使用 Post.first 而不是 allocate( :post) in a controller test?

ruby-on-rails - 解析 'ul' 和 'ol' 标签

java - PostgreSql 中的事务

ruby-on-rails - 不在 Heroku 上工作的 RoR Postgresql 时区组

ruby-on-rails-4 - Rails 4 中的引用功能

ruby-on-rails - rails 6 : Rails not defined

ruby-on-rails - Ruby:通过点击访问值

sql - 使用动态列创建表

ruby-on-rails - Rails : How do I create a custom 404 error page that uses the asset pipeline?

javascript - Rails 4 CoffeeScript 在预编译时不执行