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

时间:2013-01-09 17:09:32

标签: ruby-on-rails validation 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

1 个答案:

答案 0 :(得分: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

请注意,随着表的增长和更容易发生冲突,此算法的性能会降低。由于这个原因,UUID生成器肯定是random(1000)以上的推荐方法,因为您根本不需要手动检查冲突。