Problem returning a Proc
Ezra Zygmuntowicz
ez at engineyard.com
Tue Sep 11 16:04:40 EDT 2007
On Sep 11, 2007, at 12:53 PM, b.candler at pobox.com wrote:
> Ezra Zygmuntowicz writes:
>> There is a helper method for this that sets all the proper
>> headers and whatnot. Here is how to use it to do what your
>> example does: def world
>> res = "Hello world from #{$$} at #{Time.now}!\n"
>> render_defered do
>> sleep 5
>> res
>> end
>> end
>
> Thank you. It's "render_deferred", but when I change use that it
> works. Perhaps this example should go into the README.
> What I found surprising (and still do) is that a controller action
> can return a String directly, but a Proc cannot. Therefore, what
> exactly is it that a Proc is supposed to do to generate output,
> which a controller action doesn't have to do?
> Looking in abstract_controller.rb, I see:
> @_body = case caught
> when :filter_chain_completed
> call_action(action)
> when String
> caught
> when nil
> filters_halted
> when Symbol
> send(caught)
> when Proc
> caught.call(self)
> else
> raise MerbControllerError, "The before filter chain is broken
> dude. wtf?"
> end
> and this is also called from Controller#dispatch (via 'super')
> So at first glance, it looks like caught.call(self) ought to take
> the return value of the Proc and treat it just the same as a String
> returned directly from the controller method. But I'm clearly not
> understanding the flow of control, because that's not what's
> happening.
> Regards,
> Brian.
Brian-
That is only for a Proc returned from a before filter.
class Foo <Application
before :foo
def foo
if something?
throw :halt, Proc.new{ "Hi there!" }
end
end
end
That is how the body will be set to the output of a proc in the
dispatch method. If you don't halt the filter chain and just return a
proc as the controller body then that proc gets called later by
mongrel and it is responsible for setting the headers and content
length itself. render_deferred is the simple way to do it. but look
in the mixins/controller.rb and you will see other uses of returning
procs for streaming and whatnot. It's a low level thing and making it
so you have to deal with the headers and other stuff yourself allows
it to be a lot more flexible. Just use render_deferred if you want to
return a 'future' proc and not worry about the details.
Cheers-
-- Ezra Zygmuntowicz
-- Founder & Ruby Hacker
-- ez at engineyard.com
-- Engine Yard, Serious Rails Hosting
-- (866) 518-YARD (9273)
More information about the Merb-devel
mailing list