创建数据库条目后,我想用它做一些事情,但仍然能够在代码执行时导航页面。另外,我想看看新创建的对象在那段时间内是如何变化的。
所以我做了这样的事情:
class Penguin < ActiveRecord::Base
after_commit :do_stuff, on: [:create]
def do_stuff
#self.update(status, "doing stuff") results in an infinite loop, see https://github.com/rails/rails/issues/14493
self.update_column(:status, "doing stuff") #fix skips callback
puts "I do sleeping so here we go..."
sleep(10)
puts "...done"
#self.update(status = "done") results in an infinite loop, see https://github.com/rails/rails/issues/14493
self.update_column(:status, "done") #fix skips callback
end
end
这似乎不起作用,页面会一直加载,直到这10秒结束。我做错了什么?
我正在使用Rails 4.2.5
答案 0 :(得分:1)
您的Rails进程将一直挂起,直到完成模型回调。换句话说,在您的after_commit代码完全处理完毕之前,您的页面不会加载。
您应该考虑使用background jobs,在页面加载后将此处理推送到后台。我强烈建议您Resque(虽然现在有点过时,this RailsCast将真正帮助您开始后台工作)。
答案 1 :(得分:0)
你可以这样试试
bin/rails generate job penguins_update
然后在config/application.rb
中你可以添加任何适配器,如sidekick,resque
config.active_job.queue_adapter = :sidekiq
然后app/jobs/penguins_update.rb
class PenguinsUpdateJob < ActiveJob::Base
queue_as :default
before_enqueue do |job|
penguin.update_column(:status, "doing stuff")
end
def perform(penguin)
penguin.update_column(:status, "done")
end
end
现在你可以通过
来调用它PenguinsUpdateJob.perform_later(penguin) #this will queue it
或
如果您想立即处理而不发送到队列:
PenguinsUpdateJob.perform_now(penguin)
答案 2 :(得分:0)
谢谢你们!我查看了后台工作并决定使用Delayed Job。
如果其他人不熟悉并想尝试,请不要忘记:
Rails 4 用bin / delayed_job替换script / delayed_job
我花了一段时间,直到我决定再次彻底阅读该部分;)