更改before_save回调中的属性以通过验证?

Ale*_*kov 3 validation ruby-on-rails rails-activerecord

我有Organization一个iv属性的模型.如果iv没有设置,它是随机的,但它必须是唯一的.首先想到的是下面的回调.它不会像valid?尝试重新验证那样有效.

class Organization < ActiveRecord::Base
  validates :iv, uniqueness: true
  before_save :set_default_iv

  def set_default_iv
    self.iv ||= random(1000)

    ### is it possible to validate like this?
    # self.iv = random(1000) until valid?
 end
Run Code Online (Sandbox Code Playgroud)

Pin*_*nyM 5

使用建议的UUID生成器,或使用某种算法自己检查唯一性(例如下面的例子).但是在before_validation回调中这样做,因此验证器将捕获任何错误.

before_validation :set_default_iv

def set_default_iv
  self.iv = random(1000) until iv.present? && !collisions_exist?
end

def collisions_exist?
  class.where({:iv => iv}).
        where(new_record? ? {} : ['id != ?', id]).exists?
end
Run Code Online (Sandbox Code Playgroud)

请注意,随着表的增长和更可能发生冲突,此算法的性能将下降.random(1000)出于这个原因,UUID生成器肯定是推荐的方法,因为您根本不需要手动检查冲突.