简体   繁体   English

验证由另一个属性存在范围内的属性的唯一性

[英]Validate uniqueness of attribute scoped by another attribute presence

If I need to validate uniqueness of cat name scoped by owner so that no owner can have many cats with same name I can use that:如果我需要验证所有者范围内的猫名的唯一性,以便没有所有者可以拥有许多同名的猫,我可以使用它:

validates_uniqueness_of:name, scope: :owner_id

But how can I validate the uniqueness scoped by that the cat has owner or not?但是我如何验证猫是否拥有所有者的唯一性呢?

So that all cats that have an owner, have unique names.所以所有有主人的猫都有唯一的名字。

And all cats that don't have an owner, have unique names.所有没有主人的猫都有唯一的名字。

So it's something like scoped by scope: self.owner.present?所以它类似于scope: self.owner.present? . .

Can I do so with validations helpers without using custom validation method?我可以在不使用自定义验证方法的情况下使用验证助手吗?

You can assign a conditions clause to your uniqueness validation.您可以将conditions子句分配给您的唯一性验证。 See the documentation , which gives this example:请参阅文档,其中给出了以下示例:

class Article < ActiveRecord::Base
  validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
end

So if you wanted to ensure uniqueness for all cats with no owner, you would write所以如果你想确保所有没有主人的猫的唯一性,你会写

validates_uniqueness_of :name, conditions: -> { where(owner_id: nil) }

Or if you wanted to ensure that all cats with owners are uniquely named, regardless of who their owner is:或者,如果您想确保所有拥有主人的猫的名字都是唯一的,无论它们的主人是谁:

validates_uniqueness_of :name, conditions: -> { where.not(owner_id: nil) }

If you only want to do one or the other, that'd work.如果你只想做一个或另一个,那就行了。 However, if you want to do both, you'd find that both conditions are checked - and effectively, you're back with a uniqueness constraint that checks against the whole table, but in two queries instead of one.然而,如果你想同时做这两个,你会发现这两个条件都被检查了——而且实际上,你返回的是一个唯一性约束,它检查整个表,但是在两个查询中而不是一个。

So, if we do want both checks, we need to make sure that only one of them gets checked, which we can do with if / unless modifiers:所以,如果我们确实想要两个检查,我们需要确保只检查其中一个,我们可以使用if / unless修饰符来做到这一点:

validates_uniqueness_of :name, conditions: -> { where(owner_id: nil) },
    if: -> { owner_id.nil? }
validates_uniqueness_of :name, conditions: -> { where.not(owner_id: nil) },
    unless: -> { owner_id.nil? }

So now, if your cat has an owner ID, the validation that checks uniqueness within the scope of all records with an owner ID will run.因此,现在,如果您的猫有一个所有者 ID,则将运行检查 scope 中具有所有者 ID 的所有记录的唯一性的验证。 But if it doesn't have an owner ID, the other validation will kick in instead.但如果它没有所有者 ID,则将启动其他验证。

It means a few more hoops to jump through, but should meet your need.这意味着要跳过更多的箍,但应该可以满足您的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM