如何在Ruby on Rails中验证一对id的唯一性?

dfr*_*kow 50 validation model ruby-on-rails unique-constraint

假设在Ruby中进行以下数据库迁移:

    create_table :question_votes do |t|
      t.integer :user_id
      t.integer :question_id
      t.integer :vote

      t.timestamps
    end

进一步假设我希望DB中的行包含唯一(user_id,question_id)对.为了实现这一目标,在模型中投入的正确粉尘是什么?

validates_uniqueness_of :user_id, :question_id
似乎只是通过用户ID使行唯一,并且通过问题ID使其唯一,而不是由对唯一.

Dem*_*emi 90

validates_uniqueness_of :user_id, :scope => [:question_id]
Run Code Online (Sandbox Code Playgroud)

如果您需要包含另一列(或更多),也可以将其添加到范围.例:

validates_uniqueness_of :user_id, :scope => [:question_id, :some_third_column]
Run Code Online (Sandbox Code Playgroud)

  • @gwho**方括号**表示**数组,一系列值**.**大括号**表示**哈希,一组键值对**.我们这里没有指定键,只是值.我知道它有点晚了你可能已经知道了,但它可能有助于初学者来到这里:) (3认同)
  • 如果您喜欢`validates`语法:`validates:user_id,uniqueness:{scope:[:question_id]}` (2认同)

pak*_*eha 25

如果使用mysql,则可以使用唯一索引在数据库中执行此操作.它是这样的:

add_index :question_votes, [:question_id, :user_id], :unique => true
Run Code Online (Sandbox Code Playgroud)

当您尝试保存question_id/user_id的双重组合时,这会引发异常,因此您必须尝试并找出要捕获和处理的异常.


Jon*_*Lin 15

来自RailsGuides.validates也有效:

class QuestionVote < ActiveRecord::Base
  validates :user_id, :uniqueness => { :scope => :question_id }
end
Run Code Online (Sandbox Code Playgroud)


dpe*_*eze 14

最好的方法是使用两者,因为当唯一性验证通过时,rails不是100%可靠.

您可以使用:

  validates :user_id, uniqueness: { scope: :question_id }
Run Code Online (Sandbox Code Playgroud)

并且在安全方面100%,在您的数据库上添加此验证(MySQL ex)

  add_index :question_votes, [:user_id, :question_id], unique: true
Run Code Online (Sandbox Code Playgroud)

然后你可以使用以下方法处理你的控制器:

  rescue ActiveRecord::RecordNotUnique
Run Code Online (Sandbox Code Playgroud)

所以现在你100%安全,你没有重复的价值:)


egg*_*rop 10

除了编写自己的验证方法之外,您可以做的最好的validates_uniqueness_of是:

validates_uniqueness_of :user_id, :scope => "question_id"
Run Code Online (Sandbox Code Playgroud)

这将检查user_id在所有行中是唯一的,其中的question_id与您尝试插入的记录相同.

但那不是你想要的.

我相信你正在寻找的组合:user_id,并:question_id为整个数据库是唯一的.

在这种情况下,您需要做两件事:

  1. 编写自己的验证方法.
  2. 在数据库中创建约束,因为您的应用程序仍有可能同时处理两个记录.