From: Magnus Holm Date: 2011-01-21T06:40:46+09:00 Subject: [ruby-core:34686] Re: Returning from the callee On Thu, Jan 20, 2011 at 22:25, Rodrigo Rosenfeld Rosas wrote: > What I really want is a simple way for doing simple things. I usually use a > one-line code for a simple statement like this because it makes easier for > me for reading the code. > > If it was possible to write > > render text: 'failed' unless request.valid? > ... > render 'template/output' > > , why would I have to write things like the code below? > > unless request.valid? > �� ��render text: 'failed' unless request.valid? > �� ��return > end > ... > render 'template/output > > I don't want to give focus on special case error handling but on the usual > case instead. > > Currently, it is possible to write something like: > > return(render(text: 'invalid')) unless request.valid? This is actually possible using catch/throw, and I believe `render` in Rails worked like that in previous versions. Let me give you an example from Camping: module Helpers # Redirects to login-page unless logged in def logged_in! unless @current_user redirect Login throw :halt end end end # Inside a controller: logged_in! render :index Of course, this means that the callee actually have to add a catch-clause. It's as simple as this: def service # before: response = run_controller # after: response = catch(:halt) { run_controller } end Yes, this means that you'll have to explicitly choose how many stackframes you want to "escape" from, but that actually makes it less fragile. For instance, I could define another helper like this: module Helpers def admin! logged_in! unless @current_user.is_a?(Admin) redirect AccessDenied throw :halt end end end If logged_in! used a "return callee" approach, this wouldn't have worked because it would simply returned the admin!-method. If you use catch/throw explicitly you get more control over what you're *actually* trying to accomplish.