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