Ruby on rails 在保存前回调中更改属性以通过验证?
我有一个具有Ruby on rails 在保存前回调中更改属性以通过验证?,ruby-on-rails,validation,rails-activerecord,Ruby On Rails,Validation,Rails Activerecord,我有一个具有iv属性的组织模型。如果未设置iv,则它是随机的,但它必须是唯一的。首先想到的是下面的回调。它不起作用,因为有效?将尝试重新验证 class Organization < ActiveRecord::Base validates :iv, uniqueness: true before_save :set_default_iv def set_default_iv self.iv ||= random(1000) ### is it possib
iv
属性的组织
模型。如果未设置iv
,则它是随机的,但它必须是唯一的。首先想到的是下面的回调。它不起作用,因为有效?
将尝试重新验证
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
类组织
按照建议使用UUID生成器,或者自己使用某种算法检查唯一性(下面的示例)。但是在验证之前,请在回调中执行此操作,这样验证器将捕获任何错误
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)
,因为您根本不需要手动检查碰撞。您是否尝试过在验证前使用而不是在保存前使用?在我看来,验证前使用似乎没有任何作用,因为它不能保证唯一性,只检查iv是否已经设置。如果您在验证前这样做,然后您的验证器将检查它是否唯一。如果你想说的是你总是想要一些独特的东西,并且没有重复命中的机会,那么你可能想研究一些更像UUID的东西,它比random(1000)
@AlexeiDanchenkov具有更低的发生碰撞的可能性:验证程序的工作是保证唯一性,但不要更改该值以使其唯一,而是在不唯一时引发错误。通常,before_validation回调的工作是使用某种算法来确保验证器得到满足。然而,调用有效?
不能成为该算法的一部分,因为这将调用验证器本身。@PinnyM:你说得对。从分配中删除缓存解决了这个问题<在我看来,验证前的代码似乎用词不当。如果你回答我的意见,我会接受的。如果您能帮助我进行缓存分配,我将不胜感激(如果已经设置了iv,并且它是唯一的,那么它应该保持不变,而不是随机化)。