从控制器动态更改视图 - 在Rails中使用线程进度条

时间:2010-07-07 07:21:36

标签: ruby-on-rails multithreading progress-bar render

我有时间在我的控制器中执行任务,我想在我的视图中触发一个简单的进度条/进度状态。

在我的控制器中,我有类似

的东西
threads = []
total.times do |x|
    Thread.new {
        the_time_taking_task(x)
        #Something here to trigger the progressbar in the view
    }
end

threads.each { |aThread|  aThread.join }
render :action => 'some_action'    

我无法在其中放置渲染,因为它会抛出双重渲染错误。 我尝试放一个渲染并返回那里,我得到了'return can't jump across threads'错误

我正在尝试渲染,因为它似乎是我的控制器可以查看的唯一方式。我的方法有误吗?

在视图中需要这样简单的东西,通过该调用应用进度条宽度

<div style="width: <%= (percent_val)%>px; ">

请建议。

2 个答案:

答案 0 :(得分:6)

是的,这是一种错误的方法。

Web是无状态的,您无法阻止进程呈现视图并通过其他请求获取它。

好方法是:

1)生成队列任务而不是你的线程。您可以使用delayed_job,resque或queue系统,如rabbitMQ或beanstalkD

2)添加控制器以检查队列中的进程是否结束以及进度如何。在里面,你输入队列ID并检查是否结束并返回进度百分比。

最简单的方法是通过Ajax做到这一点。

答案 1 :(得分:2)

是的,你的做法是错误的。

shingara很好地解释了这一点。

我正在为您提供更具体的解决方案。

要获得所需效果,您基本上需要执行以下步骤:

  1. 将线程卸载到后台作业服务器。结帐resquedelayed_job
  2. 让后台作业将进度写入数据库或某些持久性介质。
  3. 在Rails中,编写一个返回当前进度的动作(如json或xml)
  4. 在您的视图中,编写一个定期的ajax请求,该请求调用在步骤3中编写的操作。
  5. 相应地更新视图。
  6. 你已经完成了! :d