validate_uniqueness_of可以使用自定义范围吗?

时间:2014-01-24 17:03:19

标签: ruby-on-rails validation activerecord activemodel named-scopes

我正在开发一个RoR项目,我希望在我的一个模型上进行唯一性验证,以检查自定义范围:

class Keyword < ActiveRecord::Base
  belongs_to :keyword_list

  scope :active, -> { where("expiration > ?", DateTime.now) }

  validates :name, uniqueness: { scope: [:active, :keyword_list_id] }
end

只是,这不起作用。它检查数据库中是否存在活动列,该列不存在并抛出此错误:

ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column keywords.active does not exist

所以,我的问题是有什么方法可以使这项工作,或者我是否必须编写自定义验证器?如果是这样,是否有关于过多地访问数据库应该是什么样的提示?

1 个答案:

答案 0 :(得分:2)

不,您必须编写自定义验证。

试试这个。

# In app/models/keyword.rb

validate :freshness

private

def freshness
  if Keyword.active.find_by(name: self.name, keyword_list_id: self.keyword_list_id)
    errors.add(:base, "Name is not fresh enough.") # Fails the validation with error message
  end
end

这是另一个有趣的观点,你不能依赖于validates_uniqueness_of或者rails中的任何其他唯一性验证器,因为验证不是以原子方式运行的,这意味着如果在同时,并且没有 SQL约束验证唯一性,ruby验证将通过,并且将插入两个记录。

我在这里要说的是,如果您的验证是关键任务,请使用SQL约束。