RJS and Content Type Header 11 comments

posted Wednesday, February 1, 2006 by topfunky

It’s great to give birth to a child, release it into the world, and see it go on to do great things that you wouldn’t have thought of.

I hope my wife doesn’t read this and get any ideas, because I’m actually talking about Gruff and Bellygraph. You can sign up for an account that lets you plot your data with your choice of colors, then post the resulting awesome graphs on your own site.

Speaking of which, patches have been submitted and I’m about to issue a release of Gruff that supports negative numbers, has better scaling if your data points don’t start at zero, and uses more consistent color/data mapping.

RJS

In yet another attempt to improve my efficiency and keep track of my time, I wrote a Rails app that uses the principles of the Printable CEO . This time I used 100% Markaby and the RJS Plugin. I hope to make it publicly available in a week or two.

RJS is a feature of the upcoming Rails 1.1 that makes it easy to send Ajax responses back as JavaScript (implemented by the dynamic duo). You can make individual calls to different elements, or send entire rendered view templates.

RJS has been applauded as an easy way to update multiple elements on a page, but I think it also fits into the flow of a web request a lot better.

I’m using observe_form to monitor changes to the task forms so you never have to hit “Submit.” By using RJS, I can create the task on the server and then send back Javascript that fires a form observer using the appropriate ID. If it was done with form_remote_tag :complete => ..., I wouldn’t know the ID and would have to start the observer in a more complicated way.

Content-Type Header

The bug that I had to fix also revealed a little bit about how RJS works. In order to fix a bug with Safari and Ajax, I was using a before_filter to set the Content-Type header to ‘text/html; charset=utf-8’ (as mentioned on the Rails Wiki). But this broke RJS. The Javascript was received, but never executed by the browser.

The solution?

The browser was getting a header like this

Content-Type: text/html; charset=utf-8

but it needs to see this

Content-Type: text/javascript; charset=utf-8

The solution was to change the before_filter to an after_filter (so Rails can set the Content-Type first, based on the actual template that was rendered). I only send the extra charset if text is being sent (some actions render a graphic image).

after_filter :set_charset

def set_charset
  content_type = @headers["Content-Type"] || 'text/html'
  if /^text\//.match(content_type)
    @headers["Content-Type"] = "#{content_type}; charset=utf-8" 
  end
end

This wouldn’t be complete without one of the functional tests that helped me debug this:

def test_rjs_header
  get :make_some_rjs, :id => 1
  assert_match @response.headers['Content-Type'], 'text/javascript; charset=utf-8'
end

def test_generated_graphic
  get :make_a_graphic, :id => 1
  assert_match @response.headers['Content-Type'], 'image/png'
  assert_match @response.headers['Content-Disposition'], %q{inline; filename="1.png"}
end

According to the Printable CEO, I get 2 points for writing a blog article. It’s time to score some more points!

11 comments

Leave a response

  • Glad you are digging rjs. Minor correction. Sam Stephenson implemented update_page and the javascript generator. I just plugged it into ActionPack by making it available as a new kind of view (with the rjs extension. So I didn’t implement rjs per se, just the infrastructure around plugging it into ActionPack.

  • I am stoked about your Printable CEO app – can’t wait to see it!

  • Wow, that’s very exciting! Can’t wait to see what you’ve done with it! Be sure to throw me a notice so I can announce it also :-)

  • Hey, very cool, Geoff! I’m in line waiting for the announcement already. And think about getting a comment from that superstar CSS Zen Garden guy :-D

  • Sweet! I’ve started an app to learn RJS too, inspired by this post. Wow. It’s sweet stuff.

    I’m looking foward to your Printable CEO app. Looks fun.

  • Thanks Geoff – you just saved me hours of pain. Now go make some babies!

  • Ed

    I am really interested in seeing this in action. Can we get a progress report and an updated ETA?

  • topfunky

    You can try it out here (documentation and features are still being added):

    http://roughunderbelly.com

  • Ehud

    I just spent 5 hours trying to figure out why my RJS was returning html headers instead of javascript. turns out I had the exact same problem you did :)

  • I’m getting an error logged each time I use this:

    @headers['Content-Type'] = 'text/xml; charset=utf-8'

    Should I be doing something different for rendering xml files?

  • topfunky

    @Manchester Rob: This article referred to an older version of Rails, and I think these issues have been solved now. So you might be fine without setting it explicitly.

Your Comment

Nuby on Rails

Geoffrey Grosenbach / Ruby / Code / Graphics / Design / Rails / Merb / Javascript / CSS

Manufactured with

Subscribe

Subscribe (RSS)