Ruby on rails 保存后Rails方法尝试反复更新记录
我遇到了一个奇怪的问题,我的应用程序似乎陷入了一个循环 我有一个名为Pages的模型,允许用户在保存时输入URL。我有一个名为process_Pages的after_save方法,如下所示 pages.rb(模型)Ruby on rails 保存后Rails方法尝试反复更新记录,ruby-on-rails,ruby,methods,model,open-uri,Ruby On Rails,Ruby,Methods,Model,Open Uri,我遇到了一个奇怪的问题,我的应用程序似乎陷入了一个循环 我有一个名为Pages的模型,允许用户在保存时输入URL。我有一个名为process_Pages的after_save方法,如下所示 pages.rb(模型) class页面
class页面
在保存URL时,我可以在开发控制台中看到,它获取了站点的HTML,但不断尝试保存记录,一次又一次地暂停页面,我必须手动退出服务器
当我再次开始备份时,记录已被添加,并按预期工作,直到我添加另一个URL
我的代码是否存在任何可能导致此连续循环的错误
谢谢你的阅读 那么self.url是否指向页面url?如果是这样的话,当您保存它时,它会点击页面的服务器,这可能会导致另一个保存和另一个url请求,等等。那么self.url是否指向页面url?如果是这样,当你保存它时,它会点击你的服务器获取页面,这可能会导致另一个保存和另一个url请求,等等。如果在创建
页面
记录之后,而不是更新页面记录之后,您只需要调用处理页面
一次,那么我建议在创建之后使用
class Page < ActiveRecord::Base
require 'open-uri'
after_create :process_pages
def process_pages
self.html = open(self.url).read
self.save
end
end
class页面
使用after\u save:process\u pages
,每次保存页面记录时都会调用process\u pages
方法。您正在process\u pages
方法中再次保存一条页面记录,该方法在\u save
回调后触发,并开始循环
有关,请参见此SO问题。
您将更好地理解为什么要进行循环。如果您需要在创建页面
记录后只调用处理页面
一次,而不是在更新页面记录后,那么我建议改为在创建
后使用
class Page < ActiveRecord::Base
require 'open-uri'
after_create :process_pages
def process_pages
self.html = open(self.url).read
self.save
end
end
class页面
使用after\u save:process\u pages
,每次保存页面记录时都会调用process\u pages
方法。您正在process\u pages
方法中再次保存一条页面记录,该方法在\u save
回调后触发,并开始循环
有关,请参见此SO问题。
您将更好地理解为什么要进行循环。这是因为您一直在重新保存循环。相反,你应该:
def process_pages
update_column(:html, open(self.url).read)
end
update\u column
正在将一列保存到数据库,跳过所有回调,因此它不会在保存回调后重新触发您的回调。然而,在保存过滤器之前,您可以使用执行一个查询,而执行两个查询是毫无意义的:
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。这是因为您一直在重新保存它。相反,你应该:
def process_pages
update_column(:html, open(self.url).read)
end
update\u column
正在将一列保存到数据库,跳过所有回调,因此它不会在保存回调后重新触发您的回调。然而,在保存过滤器之前,您可以使用执行一个查询,而执行两个查询是毫无意义的:
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。您陷入了一个循环,因为您的回调在保存后被触发,然后方法定义本身正在调用保存,导致回调再次触发
你有一些选择。您可以在保存前将回调更改为
class Page < ActiveRecord::Base
require 'open-uri'
before_save :process_pages
def process_pages
self.html = open(self.url).read
end
end
class页面
您可以在创建后更改为,
回调,该回调仅在记录创建且未更新时触发,但这可能不是所需的行为
您也可以通过调用update\u column
跳过回调,而不是调用save
,正如所指出的那样。您陷入了一个循环中,因为您的回调在save
之后被触发,然后方法定义本身正在调用save,导致回调再次触发
你有一些选择。您可以在保存前将回调更改为
class Page < ActiveRecord::Base
require 'open-uri'
before_save :process_pages
def process_pages
self.html = open(self.url).read
end
end
class页面
您可以在创建后更改为,
回调,该回调仅在记录创建且未更新时触发,但这可能不是所需的行为
您也可以通过调用update\u column
来跳过回调,而不是调用save
,正如所指出的,答案中有很多解决方法,但我想指出,您遇到了这个问题,因为您的模型做得太多了。如果您将模型视为数据库的接口,而不是可以在控制器之外访问的业务逻辑的转储场,那么您将最终创建更精简的对象,而这些对象本身(以及彼此)不会发生绊倒。谢谢@coreyward。我说的对吗?那么这种方法应该在我的项目的其他地方进行?是的,绝对正确。不幸的是,栏杆提供了很多绳子,鼓励你上吊。对于这种特殊的行为,你可能会得到最好的服务