Modifying value using before_validation before validate_uniqueness_of - SystemStackError: stack level too deep

Modifying value using before_validation before validate_uniqueness_of - SystemStackError: stack level too deep

我正在尝试确保我们存储在我的应用程序中的某些 url 的唯一性。 我想去除它们的查询参数,因为这些可以针对相同的 url 而改变,并且某些 urls 需要稍微不同的去除算法。

我有一个方法(在初始化器中)

def clean_url(url)
  domain = get_domain(url)
  case domain
  when "xyz.com" || "xyz.co.uk"
    url = url.split("&")[0]
  when "abc.com"
    url = url.split("?")[0]
  end
end

我要打电话给url_cleanerbefore_validation

thing.rb

before_validation :url_cleaner
validates_uniqueness_of :url

def url_cleaner
  self.url = clean_url(self.url)     
end

我正在

SystemStackError: stack level too deep

这里发生的事情是您的 before_validation 方法正在尝试保存对象,这又会启动 before_validation 并进入循环 - 这就是导致 SystemStackError: stack level too deep 的原因

这里造成一些混乱的是,您在该方法中选择的局部变量 (url) 与实际属性 "url" 相同,后者可通过方法 "def url".你明白我的意思吗?这里有很多不同的东西叫做 "url"。我会这样做,以便您始终只参考一件事,即 self.url。我会像这样重写上面的内容:

before_validation :clean_url
validates_uniqueness_of :url

def clean_url
  case get_domain(self.url)
  when "xyz.com" || "xyz.co.uk"
    self.url = self.url.split("&")[0]
  when "abc.com"
    self.url = self.url.split("?")[0]
  end
end

这样做还会进入循环吗?如果是这样,您能否将 get_domain 方法的定义添加到您的问题中?也许这里的某些东西正在尝试保存或验证对象。

按照 Max 上面的逻辑,我最终做了以下事情:

before_validation(on: :create) do 
  self.ad_url = clean_url(self.url) if attribute_present?("url") 
end

成功了