【问题标题】:how to make a unique column in rails active records other than id如何在除id之外的rails活动记录中创建唯一列
【发布时间】:2015-02-24 15:47:48
【问题描述】:
class CreateUsers < ActiveRecord::Migration
   def up
     create_table :users do |t|
        t.string "email", :unique=>true

我试图添加这个独特的选项来使这个电子邮件 ID 在 Rails 模型中唯一,但它不起作用,所以我怎样才能使这个电子邮件 ID 唯一?

【问题讨论】:

  • 是什么让您认为它“不起作用”?

标签: ruby-on-rails database activerecord model unique-constraint


【解决方案1】:

unique 选项应传递给 add_index 调用,而不是您定义列的位置。

如下更新您的迁移定义:

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

如果你不想允许 null 然后使用t.string :email, null: false

【讨论】:

【解决方案2】:

更新:
现在我建议不要忽略数据库级别的索引,您可以查看answer below 了解如何添加数据库唯一索引。

这不是一个好主意的原因是因为竞争条件的可能性,当应用程序的多个线程/进程几乎同时收到插入相同数据的请求时,两个线程都会检查如果电子邮件已经存在于数据库中,并且两者都会发现该电子邮件此时不存在,那么两者都将通过#validate检查,然后都将继续插入。
然后,您最终会在数据库中拥有相同的电子邮件,却不知道这是怎么发生的。

验证很有用,因为您可以对控制器中的无效记录错误做出反应。

原答案:
为什么要在 db 级别设置限制,我认为在模型级别进行验证已经绰绰有余了,至少当您需要更改或删除限制时,您不会发现自己需要添加新的迁移

class User < ActiveRecord::Base
  validates :email, uniqueness: true
end

【讨论】:

  • 因为数据完整性!
  • @PauloFidalgo 我了解,但是当您有一个包含数百万条记录的表并且想要更新索引时,您可能最终会锁定表数小时,这就是我认为使用代码级别检查的原因更实用。
  • 另外,并不是每个数据库都被限制为通过 Rails 访问,因此将约束放在数据库级别是最安全的,这样任何可能写入数据库的应用程序都将具有相同的规则集跟随。在 Rails 中使用验证主要是为了 (a) 在 Rails 应用程序本身中获取有用的错误消息,以及 (b) 启用 valid? 方法,这可能非常有用,并且可能 (c) 支持其他特定于应用的业务逻辑。
  • @MohammadAbuShady 所以你告诉我代码检查将取代 RDBMS 中的 ACID?是的,代码检查对于有效性检查是有效的,但只有一些项目不应该被忽略以保持一致性。我陈述这一点是出于对应用此逻辑的许多项目的挫败感,我不得不重新履行保管职责以清理它并将数据恢复到其他系统可以使用的水平。完全忽视系统能力让我很困惑。
  • 嗨达蒙,现在我再次阅读了这个答案,我认为将验证放在模型上而不在表上放置任何索引不是一个好主意。我在 5 年前写了这个答案,我对索引有一定的经验,这让我想避免它们。但是此时我建议不要这样做,我会更新我的答案并感谢您引起我的注意
猜你喜欢
  • 2022-07-26
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多