render behaviour in controller action

I have an odd situation which involves an unrestricted, publicly accessible, part of our application that is reached via an entirely different domain name from that of the main application. This portion has only two methods, new (with create of course) and show.

The requirements are that only the root url and the show url are valid for this domain. Anything else returns to the new action. However, if the show url is given for the initial request, in other words the new action has not previously been invoked for this session, then that too must go to the new action. Otherwise, it displays the results of the generated request on the show page.

What I tried to do was to check for the presence of a model in the show action:

def show   return new unless @model   . . . blah blah end

This worked, up to a point. If the current request did not have a model instance then even with the show url provided on the address the new method was instead invoked. However, what I discovered is that in this event the show template is rendered from within the new method nonetheless. I tried explicitly setting render :action => :new inside the new method, and this worked for the cases redirected from show. However, this causes a multiple render error in other cases.

I then tried rendering the :new action template inside show if the model was nil. That caused a nil attribute error in the new template since the model skeleton was not initialized by the new method.

My first question is: where is the show template render being set?

The second is: why does not the controller switch to the new method change the render template to the default for that action?

The third is: What is the correct way to accomplish what I am doing? Anything that gets this involved usually indicates to me that I have fundamentally misunderstood something fairly basic.

James Byrne wrote in post #968350: ...

This portion has only two methods, new (with create of course) and show.

The requirements are that only the root url and the show url are valid for this domain. Anything else returns to the new action. However, if the show url is given for the initial request, in other words the new action has not previously been invoked for this session, then that too must go to the new action. Otherwise, it displays the results of the generated request on the show page.

What I tried to do was to check for the presence of a model in the show action:

def show   return new unless @model   . . . blah blah end

I believe using a redirect is far better and simpler (although it costs 2 http requests). The main advantage I see is that than the user (a human or another computer) will see the result under the correct URL.

So that is:

def show   unless @model     redirect_to :action => 'new' # untested     return # get out of here!   end   . . . blah blah end

This worked, up to a point. If the current request did not have a model instance then even with the show url provided on the address the new method was instead invoked. However, what I discovered is that in this event the show template is rendered from within the new method nonetheless. I tried explicitly setting render :action => :new inside the new method, and this worked for the cases redirected from show. However, this causes a multiple render error in other cases.

If I need to use render the form for another action or use a redirect, I typically put a 'return' immediately after such an explicit render.

So maybe a fix for your code could be this. (but I do not prefer it, since it will render the "new" page under the "show" URL).

def show   unless @model     new # to execute the data preparations there     render :action => 'new' # this will force using the new template     return # get out of here !   end   ... # your business logic for the show end