我正在开发一个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
所以,我的问题是有什么方法可以使这项工作,或者我是否必须编写自定义验证器?如果是这样,是否有关于过多地访问数据库应该是什么样的提示?
答案 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约束。