在validate_uniqueness_of之前使用before_validation修改值 - SystemStackError:堆栈级别太深

时间:2015-03-06 11:42:21

标签: ruby-on-rails validation url

我试图确保我们在应用中存储的某些网址的唯一性。 我想剥离它们的查询参数,因为它们可以针对相同的URL进行更改,并且某些URL需要稍微不同的剥离算法。

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

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_cleaner before_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

2 个答案:

答案 0 :(得分:1)

这里发生的事情是你的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方法的定义吗?也许这里有些东西试图保存或验证对象。

答案 1 :(得分:0)

根据Max的逻辑,我最终做了以下事情:

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

这就是诀窍