codahale.com٭blog

wrestling ringtonescreate free ringtonesrooster ringtoneblake shelton ringtonecelcom free ringtone
Coda Hale lives in Berkeley, CA, where he writes about Ruby on Rails, usability, web design and development, and the occasional bit about bicycles.

Rails Plugin: xhtml_content_type

xhtml_content_type allows you to set the default MIME type for rendered .rhtml views to application/xhtml+xml if the client supports it, and only falling back to text/html for older clients.

For more information as to why this is good behavior, read this: http://hixie.ch/advocacy/xhtml

Installation

If your project is source-controlled by Subversion (which it should be, really), the easiest way to install this is via Rails’ plugin script:

./script/plugin install -x http://svn.codahale.com/xhtml_content_type

If you’re not using Subversion, or if you don’t want it adding
svn:externals in your project, remove the -x switch:

./script/plugin install http://svn.codahale.com/xhtml_content_type

Alternatively, you can just check the trunk out from the repository, if you’re super-DIY.

cd path_to_rails_app
cd vendor/plugins
svn co http://svn.codahale.com/xhtml_content_type

Usage

xhtml_content_type is super easy to use. Add the method sends_xhtml_with_correct_content_type to a specific controller, or to ApplicationController to make all controllers send XHTML properly:

  class ApplicationController < ActionController::Base
    sends_xhtml_with_correct_content_type
  end

sends_xhtml_with_correct_content_type also accepts standard filter-style conditions, if you need them:

  class MySpecialController < ApplicationController
    sends_xhtml_with_correct_content_type :except => [:seriously_weird_action]
  end
  class MyOtherSpecialController < ApplicationController
    sends_xhtml_with_correct_content_type :only => [:the_only_regular_action]
  end

You can also explicitly specify an XHTML content type using this plugin:

  def xhtml_only_action
  	render :content_type => :xhtml
  end

Have fun!

15 Responses to “Rails Plugin: xhtml_content_type”

  1. recumbentJ Says:

    I’ve installed the the plugin OK and Firefox is now seeing my app as xml, trouble is it is complaining that:

    “This XML file does not appear to have any style information associated with it. The document tree is shown below.”

    I’m using the stylesheet_link_tag link helper which seems to like appending random query strings to the end of the stylesheet url, which I guess is to get around user agent caching. E.g.:

    I’ve removed the meta tag that defined the content as text/html but that hasn’t seemed to help.

    Any ideas or am I just being a muppet?

    J.

  2. recumbentJ Says:

    Style sheet link didn’t get escaped in last comment, maybe this will work - a preview option would be nice :)

    <link href=”/stylesheets/default.css?1145397395″ media=”screen” rel=”Stylesheet” type=”text/css”/>

  3. recumbentJ Says:

    Yeah, I was being a muppet.

    Forgot to define the xml namespace. For those interested, using the following got Firefox to play ball:

    <html xml:lang=”en” lang=”en” xml‎ns=”http://www.w3.org/1999/xhtml”>

  4. Jason Barnabe Says:

    I’m trying to use this, it didn’t work at first, then after I restart I get

    ./script/../config/../vendor/plugins/xhtml_content_type/lib/xhtml_content_type.rb:45:in `remove_const’: constant Mime::HTML not defined (NameError)
    from ./script/../config/../vendor/plugins/xhtml_content_type/lib/xhtml_content_type.rb:45
    from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:21:in `require’
    from /usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require’
    from script/../config/../vendor/plugins/xhtml_content_type/init.rb:1:in `load_plugin’
    from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/initializer.rb:311:in `load_plugin’
    from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/initializer.rb:311:in `silence_warnings’
    from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/initializer.rb:311:in `load_plugin’
    from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/initializer.rb:145:in `load_plugins’
    … 10 levels…
    from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:28
    from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:21:in `require’
    from /usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require’
    from script/server:3

    and now the server won’t start.

  5. Coda Says:

    Jason: You’re using Rails 1.0. This plugin was developed for 1.1.2. Either uninstall the plugin or upgrade Rails to 1.1.2 (which, incidentally, will provide you with a myriad of other goodies, such as RJS, nested includes, and rich HABTM associations).

  6. Doug Dupory Says:

    Hello…

    I like to try it out, but have trouble installing the plugin:

    script/plugin install -x http://svn.codahale.com/xhtml_content_type
    svn: PROPFIND request failed on ‘/xhtml_content_type’
    svn: PROPFIND of ‘/xhtml_content_type’: 301 Moved Permanently (http://svn.codahale.com)

    Could the problem be the following? http://subversion.tigris.org/faq.html#301-error

  7. Coda Says:

    Sorry about that, Doug. Fixed now.

  8. Aurélien Says:

    This plugin breaks the respond_to behaviour. When I deactivate JS on my firefox, the called block is wants.js, and if not present, I get an nil.call exception.

  9. Seth A. Roby Says:

    I, too, am seeing the respond_to breakage; it appears to be a difference between the @order mime_type having the synonym for xhtml and the Mime::HTML not having it; the @responses[priority].call line in mime_responds.rb (line 166 in rev 5154) hits the nil; the [] lookup fails to find anything, but a @responses[Mime:HTML] finds the proper block. So it seems that either the @responses should be populated with the same mime-type as @mime_type_priority is populated with, or Mime::Type needs to have a better-defined equality relationship for the hash.

  10. Seth A. Roby Says:

    Okay, I’ve gotten it working. The key to the puzzle is that response.accepts builds it accept list using Mime::Type.lookup, which still pulls the old Mime::HTML from before the plugin loads, which means that it has the application/xhtml+xml synonym.

    This can be found with the new test I added to xhtml_content_type_test.rb:


    def test_mime_lookup
    const = Mime::HTML
    lookup = Mime::Type.lookup "text/html"
    assert_equal const, lookup
    end

    So we add a single line into the plugin proper:


    module Mime #:nodoc:
    remove_const('HTML') # oh we're so polite
    HTML = Mime::Type.new "text/html", :html
    LOOKUP["text/html"] = HTML
    XHTML = Mime::Type.new XHTMLContentTypeNegotiation::XHTML_MIME_TYPE, :xhtml
    LOOKUP[XHTMLContentTypeNegotiation::XHTML_MIME_TYPE] = XHTML
    end

    And now test_mime_lookup passes. But what about respond_to? Let’s add a method to our test ApplicationController:


    def with_respond_to
    respond_to do |wants|
    wants.html {render :text => 'Ich ben ein HTML'}
    wants.js {render :text => 'Ich ben ein ECMA', :content_type => :js}
    end
    end

    And a test for it:


    def test_with_respond_to
    make_controller :conditionless

    get_with_accepts :with_respond_to, 'text/html'
    assert_content_type 'text/html'

    get_with_accepts :with_respond_to, 'application/xhtml+xml,*/*'
    assert_content_type "application/xhtml+xml"

    get_with_accepts :with_respond_to, 'text/javascript'
    assert_content_type :js

    xhr :get, :with_respond_to
    assert_content_type :js
    end

    Run our tests… and they pass! Hooray for one-line fixes!

  11. Seth A. Roby Says:

    So the above worked on my Windows box, but my Mac wants one more line added to the plugin proper; LOOKUP[:html] = HTML makes it happy.

  12. Coda Says:

    Seth, thanks for the fix, and thanks for reminding me why writing software for other programmers is so much more fun. ;-)

    I’ve updated the SVN repository with your fix.

  13. toupeira Says:

    Hi, great plugin, but I noticed that it removes the charset from the Content-Type header, which my apache installation adds automatically. I worked around it by just appending it after the XHTML_MIME_TYPE, but maybe this could be made dynamic?

  14. Rob Says:

    Great plugin! Thanks.

  15. Paul Groves Says:

    Having trouble with respond_to in Rails 2.0.2 - always outputs xml when enabled. . . would appreciate any help as this is a great plugin.

    Thanks,

    Paul

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>