Rails 唯一索引和 validates_uniqueness_of 有什么区别

2024-01-01

首先,谁能解释一下唯一索引在数据库中是如何工作的?

假设我有一个用户模型name column我添加一个unique index但在模型(user.rb)中我只有一个presence上的验证器name field.

所以现在当我尝试创建两个具有相同名称的用户时,我得到 PGError

重复的键值违反了唯一约束“index_users_on_name”

所以在我看来就像unique index工作方式与uniqueness validator(?)

如果是这样那么外键呢?

可以说我有Post模型与belongs_to :user与 关联User has_many :posts。 和一个外键user_id in the posts table具有唯一索引。那么多个帖子不能有相同的user_id.

有人可以解释一下如何unique index作品?

我使用的是 Rails 4 和 Ruby 2.0.0。


这是唯一索引和validates_uniqueness_of之间的区别

这是一个补丁,使 ActiveRecord 能够识别数据库生成的唯一约束违规错误。例如,它可以在不声明 validates_uniqueness_of 的情况下完成以下工作:

create_table "users" do |t|
  t.string   "email",   null: false
end
add_index "users", ["email"], unique: true

class User < ActiveRecord::Base
end

User.create!(email: '[email protected] /cdn-cgi/l/email-protection')
u = User.create(email: '[email protected] /cdn-cgi/l/email-protection')
u.errors[:email]
=> "has already been taken"

好处是速度、易用性和完整性——

Speed

使用这种方法,您不需要在保存时进行数据库查找来检查唯一性(当索引丢失时,这有时会非常慢 -https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate.. https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate..。 )。如果您真的关心验证唯一性,则无论如何都必须使用数据库约束,因此数据库无论如何都会验证唯一性,并且这种方法消除了额外的查询。检查索引两次对于数据库来说不是问题(它在第二次被缓存),但是从应用程序中保存数据库往返是一个巨大的胜利。

使用方便

鉴于无论如何您都必须具有真正唯一性的数据库约束,一旦数据库约束就位,这种方法将使一切自动发生。如果您愿意,您仍然可以使用 validates_uniqueness_of 。

完整性

validates_uniqueness_of 一直有点像黑客——它无法正确处理竞争条件,并导致必须使用有些冗余的错误处理逻辑来处理异常。 (参见“并发性和完整性”部分http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMe... http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMe...)

验证唯一性不足以确保值的唯一性。原因是在生产中,多个工作进程可能会导致竞争条件:

  1. 两个并发请求尝试创建具有相同名称的用户(并且 我们希望用户名是唯一的)

  2. 服务器上的两个工作进程接受请求 现在将并行处理它们

  3. 两个请求都扫描用户表并看到名称是 可用的

  4. 两个请求都通过了验证并创建了一个用户 可用名称

为了更清楚地理解,请检查这个

如果您为某一列创建唯一索引,则意味着您可以保证该表不会有超过一行具有该列相同的值。在模型中仅使用 validates_uniqueness_of 验证不足以强制唯一性,因为可能有并发用户尝试创建相同的数据。

想象一下,两个用户尝试使用您在用户模型中添加了 validates_uniqueness_of :email 的同一电子邮件地址注册帐户。如果他们同时点击“注册”按钮,Rails 将在用户表中查找该电子邮件并回复一切正常,可以将记录保存到表中。然后,Rails 将使用同一电子邮件将两条记录保存到用户表中,现在您需要处理一个非常糟糕的问题。

为了避免这种情况,您还需要在数据库级别创建唯一约束:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email
      ...
    end
    
    add_index :users, :email, unique: true
  end
end

因此,通过创建 index_users_on_email 唯一索引,您可以获得两个非常好的好处。数据完整性和良好的性能,因为唯一索引往往非常快。

如果您在 posts 表中为 user_id 设置 unique: true ,那么它将不允许输入具有相同 user_id 的重复记录。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails 唯一索引和 validates_uniqueness_of 有什么区别 的相关文章

  • 如果使用 jQuery 添加字段,Rails 嵌套表单属性不会保存

    我有一个带有嵌套表单的 Rails 表单 我使用 Ryan Bates 嵌套表单和 jquery 教程 并且就动态添加新字段而言 它工作得很好 但是当我提交表单时 它不会保存任何关联的属性 但是 如果在表单加载时构建部分 则它会很好地创建属
  • Mac OSX Lion Postgres 不接受 /tmp/.s.PGSQL.5432 上的连接

    我在 Homebrew 安装 Postgres 时遇到常见的 Mac OSX 错误 No such file or directory Is the server running locally and accepting connecti
  • 黄瓜与 RSpec

    我想开始深入研究 BDD 我以前从未使用过 TDD 现在 不确定我是否应该从学习 RSpec 开始 然后跳到 Cucumber 或者直接使用 Cucumber 我一直在互联网上阅读有关两者的内容 在我看来 Cucumber 可能是 RSpe
  • 保护 REST 和 JSON

    我想利用 RESTful 架构构建提供 JSON 数据的 Web 服务 但我只想要我自己的客户端应用程序可以从我的网络服务请求 基本上 我的 Web 服务包含不供公众使用的敏感数据 但我想以这种方式构建它 以便我可以构建连接到我的 Web
  • JDBC插入实数数组

    我试图将一个真实的数组插入到 postgresql 数组中 该表的定义是 String sqlTable CREATE TABLE IF NOT EXISTS ccmBlock sampleId INTEGER block REAL 插入内
  • 用于 S3 私有文件的 ActiveStorage

    到目前为止 我一直在使用 Paperclip 将一些文件上传到 S3 其中一些文件不是公开的 Paperclip 允许通过以下位将一些文件作为私有文件上传 has attached file image styles large 2000x
  • Rails 如何使用 send_data 导出数据,然后重定向到新页面?

    我有一个 Rails 应用程序 允许用户下载生成的 CSV 文件 下载文件后 我想将用户重定向到新的 URL 或操作 有没有在 send data 之后进行重定向的技巧 我想做这样的事情 这不起作用 send data output typ
  • 如何将 devise/omniauth 重定向到我登录的页面?

    我通过omniauth 进行了身份验证 并且该链接通过layout application html haml 在每个页面上都可用 然而 当他们完成omniauth身份验证后 他们都会进入root权限 我如何设置它 以便他们重定向到他们单击
  • 无法在 Sqlite3 中添加默认值为 NULL 的 NOT NULL 列

    尝试将 NOT NULL 列添加到现有表时出现以下错误 为什么会发生这种情况 我尝试了 rake db reset 认为现有记录是问题所在 但即使重置数据库后 问题仍然存在 你能帮我解决这个问题吗 迁移文件 class AddDivisio
  • Rails content_for 和yield 之间有什么区别?

    例如 content for stuff vs yield stuff 我知道它们的实现略有不同 但是有任何真正的功能差异吗 是否有普遍接受的最佳实践 yield是您指定内容区域在布局中的位置的方式 你可能有这样的事情 div h1 Thi
  • 将记录批量插入到 Active Record 表中

    我发现我的Model create 当我一次添加大量记录时 语句需要很长时间才能运行 看着ActiveRecord 导入 https github com zdennis activerecord import wiki但它不适用于哈希数组
  • 如何让 Sidekiq 在 Heroku 上运行?

    这是我第一次尝试让 Redis 在 Heroku 上运行 我添加了一个工作dyno 就在今天 所以还没有付款 添加了RedisToGo Nano附加组件 在我的本地机器上测试了后台作业 并将应用程序推送到heroku heroku ps g
  • Heroku 没有更新 Rails 应用程序的 CSS

    我在 heroku 上更新 Rails 应用程序时遇到问题 我已经启动了我的应用程序 但我尝试更改 public stylesheets 中的 application css 文件 但每当我尝试推送到 heroku 时 CSS 都不会更改
  • Rails 3.2 防止使用错误保存对象

    我有一个 ActiveRecord 对象 我想阻止它被保存 而不对模型进行永久验证 你曾经可以使用做这样的事情errors add但它看起来不再有效了 user User last user errors add name name doe
  • 获取两行之间不同的列

    我有一张桌子company有 60 列 目标是创建一个工具来查找 比较和消除该表中的重复项 示例 我发现 2 家公司可能相同 但我需要知道这两行之间哪些值 列 不同才能继续 我认为可以逐列比较 x 60 但我寻找更简单 更通用的解决方案 就
  • 有什么方法可以加快 Postgres 位图堆扫描速度吗?

    这里是数据库新手 这是我的查询 我使用的是 Postgres 9 3 5 explain analyse SELECT SUM actual cost as cost SUM total items as num items process
  • 如何让 Redis 在 Heroku 上启动?

    我已经添加了RedistogoHeroku 上的 nano 插件 我已经在控制台中成功测试了它 但是 当我的应用程序尝试连接 Redis 时 出现以下错误 Heroku 日志文件 2011 10 12T08 19 50 00 00 app
  • Python + PostgreSQL + 奇怪的ascii = UTF8编码错误

    我有包含字符的 ascii 字符串 x80 代表欧元符号 gt gt gt print x80 当将包含该字符的字符串数据插入数据库时 我得到 psycopg2 DataError invalid byte sequence for enc
  • 以编程方式阻止 Vista 桌面搜索 (WORDS) 对映射网络驱动器上的 pst 文件建立索引

    经过几天的多次尝试 我没有找到任何 100 的解决方案来解决这个问题 我的搜寻和调查范围 直接访问注册表 HKLM SOFTWARE Microsoft Windows Search CrawlScopeManager Windows Sy
  • Docker-compose 和 Rails 控制台问题。 “在任何来源中都找不到 rake-13.0.6”

    尝试在 docker 下运行 Rails 控制台时遇到一些问题 所有其他 Rails 命令都按预期工作 但控制台却不然 octopus git master docker compose run web bundle exec rails

随机推荐