From: Rodrigo Rosenfeld Rosas Date: 2011-01-20T10:00:31+09:00 Subject: [ruby-core:34634] Returning from the callee This is a multi-part message in MIME format. --------------090505020602040109000407 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Sometimes it is useful to be able to return from the callee method. For instance, consider a web application (how innovative, this is, right?): def verify_params(params) # some calculations over params render 'Invalid params' if params.invalid? return from callee end private :verify_params def some_url(params) verify_params(params) #useful code here end def another_url verify_params(params) #useful code here end Currently, I know this can be dealt with in two ways. Most web frameworks support hooking actions, so this can be done with an even better solution, but this case was just to illustrate the feature request. Without any framework support, this could also be done like: def verify_params(params) # ... !params.invalid? end def some_url(params) return unless verify_params # ... end But, let's take another example closer to many real-case usage for the railers. Suppose you have this code on your action: def update @m = Model.find(params[:id]) @m.attributes = params[:model] render text: 'invalid' unless @m.valid? render text: 'valid' end The experienced Rails user will know this will raise a DoubleRenderError exception (in Grails it would be worse, since no exception would be raised but the results would be concatenated). That is because, although we expect that "render" is the last thing to happen while dealing with web requests, render cannot return from the callee currently in Ruby. I guess Rails would implement it that way if this was allowed in Ruby. Currently, I usually do something like "(render text: 'invalid'; return) unless @m.valid?" but I recognize this is ugly. Maybe "render text: 'invalid' and return unless @m.valid?" would work with current implementation but the API doesn't talk about return values nor it should because it doesn't make sense for 'render' to return something meaningful. I know it is not simple to allow that feature in Ruby and I'm not even talking about implementation effort, but still on language design. For instance, I guess no developer would like to have their code returned unexpected from another code that yields a "return from callee" statement. Maybe we would need something like the "friend" keyword in C++. For instance: module Renderer def render ... return from callee # this is not a proposed syntax, only the idea end end class Model include Renderer friendly end class AnotherModel include Renderer end Model.new.render # ok, returns from this context AnotherModel.new.render # raises UnfriendlyAttemptToReturnFromCallee And it would also be great to have something like class OneMoreModel < Model unfriendly Renderer #undo the "include Renderer friendly", marking it as not friendly end Am I being too crazy? I haven't been sleeping enough lately, so sorry if that doesn't make any sense to you. Rodrigo --------------090505020602040109000407 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Sometimes it is useful to be able to return from the callee method. For instance, consider a web application (how innovative, this is, right?):

def verify_params(params)
    # some calculations over params
    render 'Invalid params' if params.invalid?
    return from callee
end
private :verify_params

def some_url(params)
    verify_params(params)
    #useful code here
end

def another_url
    verify_params(params)
    #useful code here
end

Currently, I know this can be dealt with in two ways. Most web frameworks support hooking actions, so this can be done with an even better solution, but this case was just to illustrate the feature request. Without any framework support, this could also be done like:

def verify_params(params)
   # ...
   !params.invalid?
end

def some_url(params)
    return unless verify_params
   # ...
end

But, let's take another example closer to many real-case usage for the railers. Suppose you have this code on your action:

def update
    @m =
Model.find(params[:id])
    @m.attributes = params[:model]
    render text: 'invalid' unless @m.valid?
    render text: 'valid'
end

The experienced Rails user will know this will raise a DoubleRenderError exception (in Grails it would be worse, since no exception would be raised but the results would be concatenated).

That is because, although we expect that "render" is the last thing to happen while dealing with web requests, render cannot return from the callee currently in Ruby. I guess Rails would implement it that way if this was allowed in Ruby.

Currently, I usually do something like "(render text: 'invalid'; return) unless @m.valid?" but I recognize this is ugly. Maybe "render text: 'invalid' and return unless @m.valid?" would work with current implementation but the API doesn't talk about return values nor it should because it doesn't make sense for 'render' to return something meaningful.

I know it is not simple to allow that feature in Ruby and I'm not even talking about implementation effort, but still on language design. For instance, I guess no developer would like to have their code returned unexpected from another code that yields a "return from callee" statement. Maybe we would need something like the "friend" keyword in C++. For instance:

module Renderer
    def render
        ...
        return from callee # this is not a proposed syntax, only the idea
    end
end

class Model
  include Renderer friendly
end

class AnotherModel
  include Renderer
end

Model.new.render # ok, returns from this context
AnotherModel.new.render # raises UnfriendlyAttemptToReturnFromCallee

And it would also be great to have something like

class OneMoreModel < Model
    unfriendly Renderer #undo the "include Renderer friendly", marking it as not friendly
end

Am I being too crazy? I haven't been sleeping enough lately, so sorry if that doesn't make any sense to you.

Rodrigo
--------------090505020602040109000407--