Tricky respond_to and layout problem

Hi all…

I just spent the better part of an hour wrestling with a finicky
situation, and since there was some discussion earlier regarding
multiple layouts, I thought I’d share my experience in the hope it
might save someone a bit of hair-pulling :slight_smile:

In one of my controllers, I had these actions:

def welcome

end

def welcome_xml

end

def math

end

def math_xml

end

The actions sans “_xml” are simple actions that render a view. The
only difference between them is the layout used: welcome uses a one
column layout while math uses a two column layout. The two actions
that do have “_xml” are for generating xml packets of some statistics
that are related to the non-xml actions. They are sort of like a web
service in that they will be consumed by external sources (flash
movies, etc). As it was, I didn’t want the xml actions rendered in a
layout, which is where my choose_layout method came from:

def choose_layout
if action_name == ‘welcome’
‘one_column’
elsif ![‘welcome_xml’, ‘math_xml’].include?(action_name)
‘two_column’
else
nil
end
end

Using that, I got the results I desired. Until the “let’s do things
the right way” bug bit me. I looked at the xml actions and thought,
“I should be using respond_to”, so I set about making the
modifications. I changed the non xml actions to be

def welcome/math

do something

respond_to do |format|
format.html
format.xml
end
end

and made sure that my view files were welcome.rhtml/rxml and
math.rhtml/rxml. The stage was set for rails goodness to “Just
Work”…but it didn’t. When I hit /controller/math.xml, I got an
error about malformed xml. As it turned out, the xml was being
rendered in a layout. Since the action names were no longer
‘welcome_xml’ and ‘math_xml’, the choose layout method wasn’t working
as it once did. So I tried this:

format.xml {render :layout => false}

thinking that the xml view would be rendered without a layout. Well,
it was, almost. A layout was not used, but for some reason that I
could not determine, the rhtml view was rendered instead of the rxml
view, even though my url was /controller/math.xml.

Much googling didn’t really turn up a silver bullet, but enough
little pricks in the brain were generated to get some ideas
formulating. I did some experimenting with action_name and concluded
that even though I used math.xml, the action name was still math.
The only way to tell the difference between the requests was to know
what the format is. On a whim, I inspected params[:format] when I
hit /controller/math.xml. And there it was, as big as life, “xml”.
Woohoo! I ended up changing my choose_layout method to consider params
[:format], like so:

def choose_layout
if params[:format] == ‘xml’
nil
elsif action_name == ‘welcome’
‘one_column’
else
‘two_column’
end
end

and taking the {render :layout => false} off of the format.xml line.
So now it all works the way I expect, and want, it to.

Hopefully this will help someone (and maybe make up for my silly
mistakes earlier today :wink: ).

Peace,
Phillip

Hi,

On Dec 3, 2007 9:48 PM, Phillip K. [email protected] wrote:

def welcome

movies, etc). As it was, I didn’t want the xml actions rendered in a
end
format.html
as it once did. So I tried this:

format.xml {render :layout => false}

format.xml { render :xml => @foo.to_xml }

The only way to tell the difference between the requests was to know
else
Peace,
Phillip

HTH,
Michael G.

Hi Michael,

On Dec 6, 2007, at 12:25 AM, Michael G. wrote:

format.xml {render :layout => false}

format.xml { render :xml => @ foo.to_xml }

If I had a single object that could be rendered to xml, then, yes,
this would have been the simplest and most correct approach. But as
it turns out, there is some logic in my rxml view that does some
calculations before it renders the xml. I’ll do some checking to see
if there is an easier way for me to accomplish what I need to.

Thanks for the comment.

Peace,
Phillip