2010-07-07 19 views
1

J'ai une tâche de prise de temps dans mon contrôleur pour laquelle je veux déclencher une barre de progression/état de progression simple dans ma vue.Changer de vue de manière dynamique depuis le contrôleur - Barre de progression avec filetage dans Rails

Dans mon contrôleur j'ai quelque chose comme

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'  

Je ne peux pas mettre un rendu là-dedans, car il jette un double render erreur. Je essayé de mettre un rendu et il revenir et je suis arrivé « return can't jump across threads » erreur

Je suis en train de rendre comme il semble être le seul moyen mon contrôleur peut parler pour voir. Mon approche est-elle incorrecte?

Est-ce que vous voulez quelque chose de simple comme celui-ci dans la vue qui applique la largeur de la barre de progression à travers cet appel

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

conseils S'il vous plaît.

+0

Toute tâche en cours d'exécution doit s'exécuter en tant que processus en arrière-plan (de manière asynchrone et non bloquante). Comme @shingara dit utiliser delayed_job ou les goûts de celui-ci. J'ai trouvé que delayed_job est de loin le plus facile à implémenter. Passez en revue les railscasts sur delayed_job. –

Répondre

6

Oui, c'est une mauvaise approche.

Le Web est sans état et vous ne pouvez pas bloquer un processus pour afficher la vue et l'obtenir après une autre requête.

La bonne façon est:

1) Générer une file d'attente au lieu de votre tasking fil. Vous pouvez utiliser le système delayed_job, resque ou file d'attente, comme rabbitMQ ou beanstalkD

2) Ajoutez un contrôleur pour vérifier si le processus dans votre file d'attente est terminé et en quoi consiste la progression. A l'intérieur, vous mettez l'ID de la file d'attente et vérifiez si elle est fin ou non et renvoyez le pourcentage de progression.

Le moyen le plus simple est de faire cela par Ajax.

2

Oui, votre approche est incorrecte.

shingara explique bien cela. J'offre une solution légèrement plus concrète pour vous.

Pour obtenir l'effet que vous voulez, vous devez essentiellement les étapes suivantes:

  1. Offload le fil dans un serveur de travail de fond. Commander resque ou delayed_job.
  2. Demandez au travail d'arrière-plan d'écrire la progression dans la base de données ou dans un support persistant.
  3. Dans Rails, une action qui retourne les progrès en cours (comme JSON ou XML)
  4. À votre avis, rédiger une demande de paiement ajax périodique qui appelle l'action écrite à l'étape 3.
  5. mise à jour de la vue en conséquence.

Vous avez terminé! : D