如何在 Ruby on Rails 中验证一对 id 的唯一性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/923796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you validate uniqueness of a pair of ids in Ruby on Rails?
提问by dfrankow
Suppose the following DB migration in Ruby:
假设在 Ruby 中进行以下数据库迁移:
create_table :question_votes do |t|
t.integer :user_id
t.integer :question_id
t.integer :vote
t.timestamps
end
Suppose further that I wish the rows in the DB contain unique (user_id, question_id) pairs. What is the right dust to put in the model to accomplish that?
进一步假设我希望数据库中的行包含唯一的 (user_id, question_id) 对。在模型中放入什么合适的灰尘来实现这一点?
validates_uniqueness_of :user_id, :question_id似乎只是让行按用户 id 唯一,按问题 id 唯一,而不是按对唯一。
回答by Demi
validates_uniqueness_of :user_id, :scope => [:question_id]
if you needed to include another column (or more), you can add that to the scope as well. Example:
如果您需要包含另一列(或更多),您也可以将其添加到范围中。例子:
validates_uniqueness_of :user_id, :scope => [:question_id, :some_third_column]
回答by pakeha
If using mysql, you can do it in the database using a unique index. It's something like:
如果使用 mysql,您可以使用唯一索引在数据库中执行此操作。它是这样的:
add_index :question_votes, [:question_id, :user_id], :unique => true
This is going to raise an exception when you try to save a doubled-up combination of question_id/user_id, so you'll have to experiment and figure out which exception to catch and handle.
当您尝试保存 question_id/user_id 的双倍组合时,这将引发异常,因此您必须进行试验并找出要捕获和处理的异常。
回答by Jonathan Lin
From RailsGuides. validatesworks too:
来自RailsGuides。validates也有效:
class QuestionVote < ActiveRecord::Base
validates :user_id, :uniqueness => { :scope => :question_id }
end
回答by dpedoneze
The best way is to use both, since rails isn't 100% reliable when uniqueness validation come thru.
最好的方法是同时使用两者,因为当唯一性验证通过时,rails 不是 100% 可靠的。
You can use:
您可以使用:
validates :user_id, uniqueness: { scope: :question_id }
and to be 100% on the safe side, add this validation on your db (MySQL ex)
并且为了 100% 的安全,在你的数据库(MySQL ex)上添加这个验证
add_index :question_votes, [:user_id, :question_id], unique: true
and then you can handle in your controller using:
然后您可以使用以下方法处理您的控制器:
rescue ActiveRecord::RecordNotUnique
So now you are 100% secure that you won't have a duplicated value :)
所以现在你 100% 安全,你不会有重复的值:)
回答by eggdrop
Except for writing your own validate method, the best you could do with validates_uniqueness_ofis this:
除了编写自己的验证方法外,您可以做的最好的事情validates_uniqueness_of是:
validates_uniqueness_of :user_id, :scope => "question_id"
This will check that the user_id is unique within all rows with the same question_id as the record you are attempting to insert.
这将检查 user_id 在与您尝试插入的记录具有相同 question_id 的所有行中是否唯一。
But that's not what you want.
但这不是你想要的。
I believe you're looking for the combination of :user_idand :question_idto be unique across the database.
我相信你正在寻找的组合:user_id,并:question_id为整个数据库是唯一的。
In that case you need to do two things:
在这种情况下,您需要做两件事:
- Write your own validate method.
- Create a constraint in the database because there's still a chance that your app will process two records at the same time.
- 编写您自己的验证方法。
- 在数据库中创建约束,因为您的应用仍有可能同时处理两条记录。
回答by Francisco Balam
When you are creating a new record, that doesn't work because the idof your parent model doesn't exist still at moment of validations.
This should to work for you.
当您创建新记录时,这不起作用,因为在验证id时您的父模型仍然不存在。
这应该对你有用。
class B < ActiveRecord::Base
has_many :ab
has_many :a, :through => :ab
end
class AB < ActiveRecord::Base
belongs_to :b
belongs_to :a
end
class A < ActiveRecord::Base
has_many :ab
has_many :b, :through => :ab
after_validation :validate_uniqueness_b
private
def validate_uniqueness_b
b_ids = ab.map(&:b_id)
unless b_ids.uniq.length.eql? b_ids.length
errors.add(:db, message: "no repeat b's")
end
end
end
In the above code I get all b_idof collection of parameters, then compare if the length between the unique values and obtained b_id are equals.
If are equals means that there are not repeat b_id.
在上面的代码中,我得到了所有b_id参数的集合,然后比较唯一值和获得的 b_id 之间的长度是否相等。
If are equals 表示没有重复b_id。
Note: don't forget to add unique in your database's columns.
注意:不要忘记在数据库的列中添加 unique。

