Rails:页面在“after_commit执行”期间继续加载

时间:2015-12-04 10:29:29

标签: ruby-on-rails ruby-on-rails-4

创建数据库条目后,我想用它做一些事情,但仍然能够在代码执行时导航页面。另外,我想看看新创建的对象在那段时间内是如何变化的。

所以我做了这样的事情:

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

3 个答案:

答案 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

我花了一段时间,直到我决定再次彻底阅读该部分;)