Default Mime-Type Template

I have added the following to my application controller so that rails
sets the content_type header to application/xhtml+xml if the browser
accepts that mime-type and defaults to text/html otherwise.

<code>
before_filter :adjust_request_format

def adjust_request_format
    request.format = :xhtml if browser_accepts_xhtml?
end

def browser_accepts_xhtml?
    return request.env["HTTP_ACCEPT"].split(',').include?("application/
xhtml+xml")
end
</code>

I haven't added any "respond_to |format|" blocks for my actions (and I
don't want to) but instead I name my view template home.erb rather
than home.xhtml.erb and rely on the fact that if a format-specific
template cannot be found then rails will resort to using that default
template. This way I can use a single template for both the html and
xhtml formats without having to write a lick of code.

However, if the format is :html then my layout template, layouts/
application.erb will be included as expected but if the format
is :xhtml then the layout is not included for some reason. Does anyone
know why not and what I can do to get it included for the :xhtml
format without having to write respond_to blocks in all of my actions?

Setting the DOCTYPE or even the content-type meta tag to XHTML does
not actually get the browser to treat the code as XML instead of
HTML. To get it to do that you have to perform "content negotiation"
which I'm trying to do through rails but can also be done by modifying
your server settings as well.

Oh I should have also mentioned that I'm on rails 2.0.1 and have added
the following line to config/initializers/mime_types.rb:

Mime::Type.register "application/xhtml+xml", :xhtml

You mean why do I want the browser to render XHTML instead of HTML? I
dunno, just thought it would be cool to hold myself to a high standard
I guess :smiley:

Are you sure about that? http://www.xml.com/pub/a/2003/03/19/dive-into-xml.html

Well you're probably right, I'm just tinkering after all. But whether
my motivations are pointless or not I still wouldn't mind knowing the
answer to the original question I posed. That is, why does
application.erb only get included for the :html format? This could
come up in other situations besides my "pointless" one.

Ah I guess that makes sense, rails assumes that only :html will ever
need to include a layout. In my case though it needs to come up in my
xhtml template too... so can I turn "include layout" on for :xhtml
somehow in a filter or something?

I'm sorry I guess my wording is confusing templates with mime-types.
In rails 2.0 templates are named according to this pattern:
action.format.renderer

Now the "format" is important because it determines what mime-type the
page is served with. In my case html and xhtml formats serve
templates with different mime-types, text/html and application/xhtml
+xml respectively. Now you're right the templates themselves are
identical which is exactly the reason why I want to use a common one
for both html and xhtml by leaving out the "format" and naming the
template as action.erb instead of action.format.erb so that,
irregardless of the format, action.erb is the template that gets
served.

My problem is that I also want action.erb to "show layout"
irregardless of the format but it only shows layout when the format is
html. However I think I can live with the fact that this is just a
rails "assumption" and a good one at that so I'm content with leaving
it be for now.

No need to be so hostile Ryan. Browsers really do ignore the DOCTYPE
and serve HTML... I'm observing it with Firefox 2.0 right now... in
the year 2007....

Oh and sorry I guess shouldn't be saying that browsers "serve" html
but rather they "parse" or "render" HTML unless you explicitly tell
them not to by setting the content_type response header to the
appropriate xml mime-type.

google "application/xhtml+xml versus text/html" for enlightenment :slight_smile:

A fairly concise summary can be found here, BTW:
  <http://www.sitepoint.com/forums/showthread.php?t=393445>

HTH!

I'm sure if you wrote up a whole valid XHTML page and put it on your Ruby On
Rails site and ran it through the same validator, it would still be valid.

Except XHTML is not supposed to be served as text/html, but that's
another story.

I have nothing more to say about the matter. I believe it's an attempt at
doing something irrelevant, or a very good attempt at trolling.

Well, sorry to disappoint, but your believes need some adjustment. While DOCTYPE
does not do much more than prompting browsers to use particular rendering mode
(standards, quirks, etc.) and informing validators which standard to
check code against,
MIME types prompt browsers to use different parser.
For a starter that means that Internet Explorer will not render the
page, but will offer you to download it. Yes, IE does not support
proper XHTML (by proper I mean XHTML code served as
application/xhtml+xml), even in IE7.
The next important point is, that if you have any error in your code
your users are likely
to get "Yellow page of death" (
http://en.wikipedia.org/wiki/Yellow_Screen_of_Death#Yellow ) instead
of the page content.
And there is more: CSS is interpreted differently (selectors are case
sensitive, so if you have uppercase selectors in CSS they will be
ignored; html/body is treated differently), comments are interpreted
differently, only five entities allowed (so &copy;
will give you nice yellow page of death), Javascript may cause more
errors, document.write no longer works, you should use different
methods for DOM manipulation (e.g. createElementNS vs. createElement),
etc.

You can learn more here:
http://www.hixie.ch/advocacy/xhtml (old classic)
http://lachy.id.au/log/2005/12/xhtml-beginners
http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/
http://wiki.whatwg.org/wiki/HTML_vs._XHTML
http://annevankesteren.nl/2004/07/mime

I prefer HTML 4.01 Strict, but if someone chooses to use XHTML then it is good
to know trade offs, gotchas and things Zeldmand did not tell you…

Regards,
Rimantas

I have added the following to my application controller so that rails
sets the content_type header to application/xhtml+xml if the browser
accepts that mime-type and defaults to text/html otherwise.

*snipped example code*

I haven't added any "respond_to |format|" blocks for my actions (and I
don't want to) but instead I name my view template home.erb rather
than home.xhtml.erb and rely on the fact that if a format-specific
template cannot be found then rails will resort to using that default
template. This way I can use a single template for both the html and
xhtml formats without having to write a lick of code.

However, if the format is :html then my layout template, layouts/
application.erb will be included as expected but if the format
is :xhtml then the layout is not included for some reason. Does anyone
know why not and what I can do to get it included for the :xhtml
format without having to write respond_to blocks in all of my actions?

Hi Adam,
  did you make any progress on these issues?

I prefer xhtml too, especially during development. Browser errors on
malformed markup is a great way to catch errors quickly.

Regards,
Isak

Hi Isak,

I ended up cheating a bit and omitting the format from my view names
but specifying it for my layouts and then getting the layouts to
render a common partial.

So my views are named "home.erb", "about.erb", and my layout is in
"layouts/_application.erb". I have "layouts/application.html.erb" and
"layouts/application.xhtml.erb" but those both contain this single
line: <%= render partial => 'layouts/application' %>

It's a bit of a workaround, I know, but my controller is very clean as
a result of my being able to rely on rails' conventions rather than
coding everything explicitly.

Rimantas thanks for clearing things up in your post and linking to
those articles. I found them very enlightening. Hopefully Ryan did
too :wink:

Adam