вторник, мая 30, 2006

RJS update and redirects

Recently I've ran into problem with processing redirects with Ajax.
First solution that I've found was using custom status code handler in link_to_remote (and some other functions), like this:


<% link_to_remote "Foo",
:url => { :action => "foo" },
302 => "document.location = request.getResponseHeader('location')" %>

But I've got problems with it:
1. It didn't work for me
2. I find it rather harassing to add 302 => .... to every link_to_remote function (which sometimes are hidden deep inside helper methods)

Second attempt to solve this problem was using RJS redirect_to:


render :update do |page|
page.redirect_to '/some/url'
end

This worked fine but had some unwanted side-effects: when redirect is rendered it appeared on a page inside updated element while browser was preparing to do the redirect.
After some investigation I've found out that the javascript was sent with content-type of 'text/javascript' and plain text (without any <script> tag surrounding). That's why after Prototype's Ajax.Updater inserted it into update element it showed up. Then I dug some Prototype's sources and found out that it can strip <script> tags and evaluates everything inside it (if needed). So, my solution was to alter ActionController::Base.render_javascript
to surround javascript code with <script> tags if it was Ajax request.

Here is the code:


module ActionController
class Base
def render_javascript(javascript, status = nil) #:nodoc:
if @request.xhr?
render_text("<script type="'text/javascript'">#{javascript}</script>", status)
else
@response.headers['Content-Type'] = 'text/javascript; charset=UTF-8'
render_text(javascript, status)
end
end
end
end




I found out that content-type recongnition is implemented in Prototype v1.5something... So there is no need to patch render_javascript anymore...

Just be sure to run "rake rails:update:javascripts"

Комментариев нет: