views:

2738

answers:

4

I'm using rails, but doing all my Javascript unobtrusively using jQuery in application.js.

Unfortunately, this makes it quite difficult to reference URLs. For example, if I want to give a field autocomplete behavior, I have to hard-code the autocomplete URL in application.js since the rails url_for isn't available.

Is it possible to make application.js use erb? Am I thinking about this the wrong way?

+2  A: 

Yes, it's possible, on current rails versions just call your file application.js.erb; on older versions you can either roll your own or grab something like this.

MarkusQ
Cool! Is this the best practice here? Do you use this method? It sounds good to me, but I'm still nervous I'm working against the grain.
Horace Loeb
AFAIK, it made it into rails because so many people were doing it on their own. It's a very common usage pattern. One caveat: this is for injecting semi-static things like the routes; if the contents are going to change within a session, send the javascript in a ajax wrapper instead.
MarkusQ
Actually this doesn't seem to work -- do I have to move the file out of /public/javascripts? If I just rename the file I get a routing error when my browser requests 'application.js'.
Horace Loeb
+1  A: 

Don't do application.js.erb , that's not a good practice even if caching is involved. Make you autocomplete endpoint (url from which you are getting the data) the same as your form's action url. In your application.js just append &ac=1 to it and make your controllers understand it.

skrat
+3  A: 

You could add the url to an attribute on the form or form field, if you don't mind markup that may not pass the validator, and then fetch that attribute with jQuery.

It looks like Rails 3.0 might be going down this route with the javascript helpers using HTML5 custom data attributes: DHH @ Railsconf 09

Marc Roberts
+1  A: 

You don't have to hardcode it-- just create a single JS function that adds the autocomplete listener, and accepts parameters for the autocomplete, and call that JS function from your template:

(code simplified for clarity)

application.js:

function add_autocomplete(id, url) {
   $("#" + id).autocomplete(
      source: url  
   );
};

application_helper.rb:

def add_autocomplete(id, url)
  render :text => "<script> add_autocomplete('#{id}', '#{url}');</script>"
end

ERb template:

<input id="i_want_autocomplete" />
<%= add_autocomplete("i_want_autocomplete", items_js_path() %>
joshwa