This is my current sequence of actions:
-
I have a link_to in a rhtml file that when clicked on calls a method
in my controller
-
This method runs through a loop
-
At some points in this loop i would like to be able to stop and update
something in my rhtml file (and hence the webpage), and then continue
back on with the loop
-
is this possible?
James S. wrote:
This is the fundamental problem with responsive GUIs - you can’t just go
into a loop from an event handler.
(Note that everything from the Model down thru the database is just one
huge
system to keep the GUI responsive without looping over updating data and
such…)
If I had this problem with a desktop GUI (such as a Win32 window), I
would
start a window timer, and then “time slice” the loop. I would store its
looping index in a window variable, and at each timer tick I would
update
the index, run one tick of the looped activity, and then optionally
update
the screen.
Desktops prefer that system (it’s often a better design than threading),
and
they allow window timers with 0 duration, to execute each time the CPU
is
idle. The result is perfectly responsive, and you obviously can’t do it.
The new pattern here is to use periodically_call_remote, and then do a
small
batch of items. Maybe loop until you find a reason to update the screen.
Then return an update, store your looping index, and await the next
event.
But you can’t set periodically_call_remote to less than a second,
because it
slowly beats the crap out of every layer in your system, from the
browser to
the server.
The next more sadistic technique would be to start a timer (or possibly
even - shudder - a thread) in the server. It will loop thru items, and
push
window updates as objects into a database queue. Then you use
periodically_call_remote, with an easier frequency, to pop that queue
and
update the browser. Note that storing the queue in the database takes
care
of all the ACID concurrency the queue needs, and starting a new thread
might
be safe. Only do that as a last resort - look for a timer system so
Rails
can send its unused CPU cycles to your background task.
–
Phlip
Redirecting... ← NOT a blog!!!
Going into more detail with my problem, what i’m trying to do is get
input from the user. So basically, the user will click on a link on the
webpage, a method in the controller will be called. This method is a
loop, and at some point a condition will be true and i need to display a
prompt, or reveal a text field on the webpage, allowing the user to
input a string, which will be fed back into a variable in the
controller.
This is the fundamental problem with responsive GUIs - you can’t just go
into a loop from an event handler.
If I had this problem with a desktop GUI (such as a Win32 window), I
would
start a window timer, and then “time slice” the loop. I would store its
looping index in a window variable, and at each timer tick I would
update
the index, run one tick of the looped activity, and then optionally
update
the screen.
The problem is that i am dealing with two different languages that are
executed at different times (ruby, javascript). With my specific
problem, on a desktop GUI, i would just call another method at the point
of update, which would display a prompt, allowing the user to enter a
string. When the user had entered input and confirmed, the method would
just return a string to the initial method… easy.
I have tried to solve my problem by using a RJS template for the method
in the controller that is executed when the link in the webpage is
clicked. So I put my ruby loop in there and when i need to alter the
rhtml file i can use javascript. However this javascript is only
executed after the loop has completed…
I didn’t really want to go down the route of periodically checking a
variable to then render an update in the view, do i have a choice?
Thanks for your response.
On Dec 10, 2006, at 2:42 PM, James S. wrote:
the index, run one tick of the looped activity, and then optionally
just return a string to the initial method… easy.
Thanks for your response.
James-
You can't really do what you are thinking of with stock rails
because it doesn no output buffering. the response will not get sent
to the browser until it is entriely done rendering everything. You
cannot call a render in a loop and have it update the page each time
thru the loop. You probably want to look into comet style push
server. There is a rails plugin called jugernaut that may help you.
Or you may want to look into backgroundrb.
WHat you want is very difficult to do over HTTP which is a stateless
protocol. You are trying to apply desktop app semantics to web apps
and it doesn’t convert over very well.
Cheers-
– Ezra Z.
– Lead Rails Evangelist
– [email protected]
– Engine Y., Serious Rails Hosting
– (866) 518-YARD (9273)
Ezra Z. wrote:
WHat you want is very difficult to do over HTTP which is a stateless
protocol. You are trying to apply desktop app semantics to web apps
and it doesn’t convert over very well.
Which is why everyone does it using periodically_call_remote(), slogging
the
browser and the server. GMail allegedly does it by leaving the Ajax wire
open and never (deliberately) closing it. One could do that with raw
HTTP,
but how do you get a handle to the server’s socket from inside Rails??
–
Phlip
Redirecting... ← NOT a blog!!!