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 B. 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