The DoubleRenderError exception recently introduced is forcing me to go back and rewrite my apps authentication handler. Before I could do a redirect right in the middle of a request. Whatever was happening after that went unnoticed, I assumed it was simply ending the request after the redirect was called, but apparently it was going on and rendering the page. Why can''t a redirect simply halt execution of the action? Is there a way to rescue the exception outside of the controller and gracefully exit? -Jeff _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
>Whatever was happening after that went unnoticed, I assumed it was simply > ending the request after the redirect was called, but apparently it was going > on and rendering the page.If you do your authentication in a before_filter (which you probably should, unless you have a specific reason not to), just return false from the filter and execution will stop. That''s how the login generator does it... If your authentication code doesn''t return false, exit, throw an exception, or do something drastic like that, you should probably alter it so it does. I''ve seen too many php scripts that do authentication by something like if(!$_SESSION["logged_in"]) { header("Location: login.php"); } When you hit that page and you''re not logged in, you do get redirected. If you modify your user-agent to ignore http redirects, however, you can see the page''s content just fine, even if you''re not logged in. Just something to be aware of :) Tyler
Well it is not just my authentication handler, things have broken all over my application... I''ll do stuff like this def generic_action @data = @order.generic_data ||= GenericData.new if @request.post? @data.attributes = @params[''data''] redirect_to :action => next if @data.save end end Now I have to "return redirect_to" everywhere instead. It''s just clutter. I think if I were able to rescue the exception at some good place without modifying the base libraries, perhaps with a configuration option, I could keep my code nice and simple and not have to return out of the action. Or, it could simply not render anything after the first one, instead of throwing the exception. I can think of some instances when I would actually want to render multiple pages. It just seems like an unnecessary limitation. What purpose does it serve? Was it added to facilitate something else? I''d like a simple way to revert back to the old behavior. -Jeff ----- Original Message ----- From: "Tyler Kiley" <tyler.kiley-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> To: <rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org> Sent: Wednesday, July 06, 2005 3:29 PM Subject: Re: [Rails] DoubleRenderError exception>Whatever was happening after that went unnoticed, I assumed it was simply > ending the request after the redirect was called, but apparently it was > going > on and rendering the page.If you do your authentication in a before_filter (which you probably should, unless you have a specific reason not to), just return false from the filter and execution will stop. That''s how the login generator does it... If your authentication code doesn''t return false, exit, throw an exception, or do something drastic like that, you should probably alter it so it does. I''ve seen too many php scripts that do authentication by something like if(!$_SESSION["logged_in"]) { header("Location: login.php"); } When you hit that page and you''re not logged in, you do get redirected. If you modify your user-agent to ignore http redirects, however, you can see the page''s content just fine, even if you''re not logged in. Just something to be aware of :) Tyler _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
> def generic_action > @data = @order.generic_data ||= GenericData.new > if @request.post? > @data.attributes = @params[''data''] > redirect_to :action => next if @data.save > end > endThis should continue to work, I have stuff like this all over my application which has been running on edge rails for a while.> Or, it could simply not render anything after the first one, instead of > throwing the exception. I can think of some instances when I would actually > want to render multiple pages. It just seems like an unnecessary limitation. > What purpose does it serve? Was it added to facilitate something else? I''d > like a simple way to revert back to the old behavior.This behaviour has never worked. The only difference now is that instead of failing silently, we tell you that something isn''t working. render_text "aaa" render_text "BBB" has never rendered "aaaBBB" -- Cheers Koz
Some more commentary on this: http://tech.rufy.com/entry/61 On Jul 6, 2005, at 5:29 PM, Michael Koziarski wrote:>> def generic_action >> @data = @order.generic_data ||= GenericData.new >> if @request.post? >> @data.attributes = @params[''data''] >> redirect_to :action => next if @data.save >> end >> end >> > > This should continue to work, I have stuff like this all over my > application which has been running on edge rails for a while. > > >> Or, it could simply not render anything after the first one, >> instead of >> throwing the exception. I can think of some instances when I >> would actually >> want to render multiple pages. It just seems like an unnecessary >> limitation. >> What purpose does it serve? Was it added to facilitate something >> else? I''d >> like a simple way to revert back to the old behavior. >> > > This behaviour has never worked. The only difference now is that > instead of failing silently, we tell you that something isn''t working. > > render_text "aaa" > render_text "BBB" > > has never rendered "aaaBBB" > > -- > Cheers > > Koz > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Duane Johnson
2005-Jul-07 14:41 UTC
How about a redirect_to! method? (was Re: DoubleRenderError exception)
May I suggest a redirect_to! method? Here is some code I picked off the RAA, called "ruby-goto": ## goto.rb STACK = [] class Label attr_accessor :name; attr_accessor :block; def initialize(name, block); @name = name @block = block end def ==(sym) @name == sym end end class Goto < Exception; attr_accessor :label def initialize(label); @label = label; end end def label(sym, &block) STACK.last << Label.new(sym, block) end def frame_start STACK << [] end def frame_end frame = STACK.pop idx = 0 begin for i in (idx...frame.size) frame[i].block.call if frame[i].block end rescue Goto => g idx = frame.index(g.label) retry end end def goto(label) raise Goto.new(label) end And from the goto_test.rb file: ## goto_test.rb require ''goto'' def test frame_start label(:start) { goto :b } label(:a) { print "world!\n"; goto :c } label(:b) { print "hello "; goto :a } label(:c) frame_end end frame_start label(:a) { test } label(:b) { goto :a } frame_end Does this seem like a viable solution? Duane Johnson (canadaduane) _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Jeff,> def generic_action > @data = @order.generic_data ||= GenericData.new > if @request.post? > @data.attributes = @params[''data''] > redirect_to :action => next if @data.save > end > endThat will work. I''m assuming that you''re running into problems because you have an explicit render call at the bottom of your generic_action. If you rely on rails'' implicit rendering, you''re fine, but if you call it yourself, you get the exception. My only beef with the DoubleRenderException is that a redirect_to counts as a render, which is kinda non-intuitive the first time you run into it. It took me a while to figure that out.