我遇到了一个奇怪的问题,我的应用似乎陷入了困境。
我有一个名为Pages的模型,允许用户在保存时输入URL我有一个名为process_pages的after_save方法,如下所示
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?
我的代码是否有任何问题导致这种连续循环?
感谢阅读!
答案 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指向页面网址吗?如果是这样,当你保存它时,它会命中你的服务器页面,这可能会导致另一个保存和另一个网址请求等。