I''ve talked to Yehuda today (actually yesterday, at least in my time
zone) and we come to some solutions.
First, he pointed me out the config.threadsafe! method, regarding the
ability to handle multiple connections concurrently in a single Rails
instance:
http://api.rubyonrails.org/classes/Rails/Configuration.html#M002542
Then, he remembered me why it is complicated to support forcing
flushing from inside an ERB. In Rails, we can set variables in a view
that will then be available when the layout is applied. This requires
Rails to process all the view before sending any output to browsers.
Then I tried to handle the ERB manually from inside the controller
using the "render :text => proc" approach. See the Streaming
section
in:
http://api.rubyonrails.org/classes/ActionController/Base.html#M000658
First, some comments before the solution so that I can remember myself
to update the documentation. Here is the example from API:
# Streams about 180 MB of generated data to the browser.
render :text => proc { |response, output|
10_000_000.times do |i|
output.write("This is line #{i}\n")
output.flush
end
}
Apparently, output.flush is deprecated since flushing is handled
automatically, thus, this line should be removed from documentation.
One more thing: the above code won''t work with Rails 3 beta, at least.
Actually I had other problems with Rails 3 beta. For instance:
- Usually, if one has multiple Rails installations and want to use
some specific version to create an application, he can do "rails
_2.3.4_ new_app". That won''t work after installing Rails 3 beta.
Worse, it is not possible either to run the Rails binary from rubygems
installation because of some strange problem I couldn''t understand
what the cause was. So, I had to uninstall Rails 3 beta before I could
achieve the solution I''ll present next.
This was the solution I''ve found for my needs with the help of Yehuda:
Created a Rails 2 application and created a controller like this:
class TestController < ApplicationController
def index
render :text => proc { |response, output|
response.content_type = ''text/plain''
v = ActionView::Base.new([],{},self)
v.instance_variable_set(''@output'', output)
output.write ERB.new(IO.read((Rails.root+''app/views/test/
index.html.erb'').to_s)).result(v.send :binding)
}
end
end
And the view index.html.erb:
<% 100.times do |i| %>
<%= "Number #{i} " * 1000 %>
<% @output.write _erbout
_erbout = ''''
sleep(1)
end %>
Of course, with this solution one should write the entire HTML output
since it will not use any layout as it is. But that is not a problem
for me.
Hope this helps others. If not, at least it will be useful for me not
to forget the solution ;)
I''m planning updating Layout and Rendering guide to cover this
situation.
But I have another pending doubt I''ve just realized...
How can I trigger an action when the user cancel the request? My
report can take hours to complete and I would like Rails to stop
processing the request when the user interrupts the connection (by
canceling loading in the browser, for instance). Is that possible? I
know I''m pushing Rails limits here, but hey! What would be the fun
part if we don''t do that! ;)
Thank you once more, Yehuda.
Best regards,
Rodrigo.
On 18 fev, 20:30, Rodrigo Rosenfeld Rosas <rr.ro...@gmail.com>
wrote:> How can I force flushing an ERB output?
>
> I have a report that yields a very big HTML table that can take hours to
> finish processing depending on input params.
>
> I would like to flush the already generated output to the browser even
> if the result is not complete. The idea is send the table lines once
> they are generated. Waiting for the entire output to be generated also
> could consume a lot of RAM, although it is not a major problem now, but
> flushing the output from time to time would allow less memory usage.
>
> Just in case some of you have some experience with JRuby or could
> enlight me understanding another problem, let me ask you another
> question. The calculations I''m performing for generating this
table are
> quite heavy and I''m using some Java libraries to help me
performing
> them. I''m not using ActiveRecord to talk to the database, but
Sequel
> instead in the Ruby part. I''m also using warbler to generate a war
file
> to be deployed in a Java servlet container, such as Tomcat.
>
> I would like to understand better why isn''t Rails thread-based. I
mean,
> why there is a need for multiple instances of Rails for dealing with
> concurrent connections? If this limitation is specific for ActiveRecord
> or MRI Ruby implementation, it shouldn''t be a problem for my
> application, since it uses JRuby (with real threads) and does not depend
> on ActiveRecord. Is there anything I could do to allow multiple
> concurrent connections in a single Rails instance?
>
> Thanks in advance,
>
> Rodrigo.
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core@googlegroups.com.
To unsubscribe from this group, send email to
rubyonrails-core+unsubscribe@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/rubyonrails-core?hl=en.