Rails after_save方法试图反复更新记录

时间:2014-03-26 22:42:32

标签: ruby-on-rails ruby methods model open-uri

我遇到了一个奇怪的问题,我的应用似乎陷入了困境。

我有一个名为Pages的模型,允许用户在保存时输入URL我有一个名为process_pages的after_save方法,如下所示

pages.rb(model)

class Page < ActiveRecord::Base
  require 'open-uri'

  after_save :process_pages

  def process_pages
    self.html = open(self.url).read
    self.save
  end 
end

在保存URL时,我可以在开发控制台中看到它获取网站的HTML,但尝试不断地一遍又一遍地保存记录停止页面,我必须手动退出服务器。

当我再次开始备份时,记录已添加并按预期工作,直到我添加另一个URL?

我的代码是否有任何问题导致这种连续循环?

感谢阅读!

4 个答案:

答案 0 :(得分:2)

由于你的回调是在保存后触发,然后方法定义本身正在调用保存,导致回调再次触发,因此您陷入循环。

你有一些选择。您可以将回调更改为before_save

class Page < ActiveRecord::Base
  require 'open-uri'

  before_save :process_pages

  def process_pages
    self.html = open(self.url).read
  end 
end

您可以更改为仅在创建记录并且未更新记录时触发的after_create回调,但这可能不是所希望的行为。

您也可以拨打update_column来跳过回调,而不是按照@BroiSatse

的指示调用save

答案 1 :(得分:1)

如果您需要在创建process_pages记录后而不是在更新网页记录之后再次致电Page ,那么我建议您请改用after_create

class Page < ActiveRecord::Base
  require 'open-uri'

  after_create :process_pages

  def process_pages
    self.html = open(self.url).read
    self.save
  end 
end

使用after_save :process_pages时,每次保存Page记录时都会调用process_pages方法。您正在process_pages方法中再次保存网页记录,这会触发after_save回调并开始循环。

difference between after_save and after_create ,请参阅此SO问题。 你会更好地理解你为什么要进入循环。

答案 2 :(得分:1)

这是因为你一直在重新开始。而是做:

def process_pages
  update_column(:html, open(self.url).read)
end

update_column正在将一列保存到数据库中,跳过所有回调,因此它不会重新触发你的after_save回调。然而,当您使用before_save过滤器执行两个查询时,执行两个查询是毫无意义的:

before_save :process_pages

def process_pages
  self.html = open(self.url).read
end 

但可能最好的方法是覆盖url方法的setter:

def url=(value)
  super
  self.html = open(self.url).read
end

这样您就可以在保存模型之前使用页面html。

答案 3 :(得分:0)

self.url指向页面网址吗?如果是这样,当你保存它时,它会命中你的服务器页面,这可能会导致另一个保存和另一个网址请求等。