views:

1288

answers:

5

Some content in my page is loaded dynamically with the use of this code :

javascript_tag( remote_function( :update => agenda_dom_id, :url => agenda_items_url(options), :method => :get ) )

When it outputs in the browser, it comes out as this :

new Ajax.Updater('agenda', 'http://localhost:3000/agenda_items?company=43841&history=true', {asynchronous:true, evalScripts:true, method:'get'})

The & character in the URL is replaced by & and so the second parameter of the request is discarded.

I made different tests and it looks as if Rails tries to make the HTML entities conversion as soon as it detects that the code is in a script tag. And trying to hardcode the link or the javascript tag didn`t change anything.

Anybody encountered this problem before?

+1  A: 

All javascript characters are escaped (see the source of remote_function). That has some consequences. However in your case I don't see any problem, I have similar cases where this just works.

Can you describe the problem you have with it?

PS. I have posted I lighthouse ticket because I have a case where I need to insert javascript: https://rails.lighthouseapp.com/projects/8994/tickets/2500-remote_function-does-not-allow-dynamically-generation-of-url#ticket-2500-2

A: 

The problem is with the URL that gets generated :

http://localhost:3000/agenda_items?company=43841&history=true

The history parameter won't get sent correctly since the & character is replaced by a &.

The funny thing is that when I try it with a link_to_remote instead of the remote_link or when I output the remote_function directly on the page (and not in a script tag), it works as expected and doesn't escape the & character with its HTML entity.

I'm on Rails 2.1.1 and Firefox. Maybe it has been fixed in the latest version of Rails but switching is not an option right now.

Pierre Olivier Martel
A: 

I'm on Rails 2.3.2 and I don't have any problem when & is replaced by & amp;

If you need to fix this in your situation, you could patch the remote_ function update and add a :escape_ url option and set that to false. Put the code below somewhere in your rails environment where it gets loaded.

module ActionView
class Base
 def remote_function(options)
  javascript_options = options_for_ajax(options)

  update = ''
  if options[:update] && options[:update].is_a?(Hash)
    update  = []
    update << "success:'#{options[:update][:success]}'" if options[:update][:success]
    update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure]
    update  = '{' + update.join(',') + '}'
  elsif options[:update]
    update << "'#{options[:update]}'"
  end

  function = update.empty? ?
    "new Ajax.Request(" :
    "new Ajax.Updater(#{update}, "

  url_options = options[:url]
  url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
  function << (options[:escape_url] == false ? "'#{url_for(url_options)}'" : "'#{escape_javascript(url_for(url_options))}'") ## Add this line to the rails core
  function << ", #{javascript_options})"

  function = "#{options[:before]}; #{function}" if options[:before]
  function = "#{function}; #{options[:after]}"  if options[:after]
  function = "if (#{options[:condition]}) { #{function}; }" if options[:condition]
  function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm]

  return function
end 
end

end

A: 

Use the :with option (which must be a valid query string and is not escaped like the :url), like so

url, query_string = agenda_items_url(options).split('?')
javascript_tag( remote_function( :update => agenda_dom_id, :url => url, :with => query_string, :method => :get ) )

I'm assuming agenda_items_url is your own helper function and it is outputting the full url without escaping it first.

+1  A: 

Guys, it's just a default behavior of url_for in views... C'mon, pass :escape => false along with URL params and enjoy unescaped stuff :)

Anton