Andy Harvey
Andy Harvey

Reputation: 12653

How to use Ruby in a Javascript function?

I realize this is not possible in the way my question is worded, but is there a way to still get the outcome I'm looking for.

In a Rails 3.2 app I have a form with City and Location fields:

<%= f.select :city, City.all, :prompt => "Select..." %>
<%= f.input :location_name, :input_html => {    data:{ autocomplete_source: Location.order(:name).map(&:name) } } %>

The location field uses Twitter Bootstrap's typeahead function to display an autocomplete list of entries.

A Location belongs to a City. I want to filter the list of autocomplete entries based on the City value selected by the user.

Basically, I need to dynamically change

... autocomplete_source: Location.order(:name).map(&:name) ...

to

... autocomplete_source: Location.where('city_id => ?', '@myform.city.id').order(:name).map(&:name) ...

In coffeescript I could do something like:

jQuery -> 
  $('#myform_city_id').change ->
    $('#myform_location_name').attr('data-autocomplete-source','#{Location.where(city_id: @myform.city_id).order(:name).map(&:name)}')

But the active record query is not called, it simply gets passed in as a string.

What is the best way to dynamically change this autocomplete-source attribute with the new query?

Upvotes: 0

Views: 168

Answers (2)

Angelo
Angelo

Reputation: 492

Rename your coffeescript from filename.js.coffee to filename.js.coffee.erb. Then you can do something like this:

jQuery -> 
  $('#myform_city_id').change ->
    $('#myform_location_name').attr('data-autocomplete-source','<%= Location.where(city_id: @myform.city_id).order(:name).map(&:name) %>')

Upvotes: 0

YuriAlbuquerque
YuriAlbuquerque

Reputation: 2245

You can't do this because Javascript is on the client side, Ruby is running on the server side. The Javascript does not "see" Ruby, because of this (ERB is a little different: it is transformed into a HTML before the client receives it). I recommend you to do this through an Ajax solicitation.

Explaining better: you make an action from a controller that gives you a JSON representation of what you want (it could be even a existing controller, but send it as a JSON). You call this controller via Ajax (using :remote => true on your link). You bind the ajax:complete response event from that link to a function, like this:

$("#link_id").bind "ajax:complete", (e, xhr, settings) ->
    #TODO function body goes here

Or this:

$("#link_id").bind "ajax:complete", functionName

Inside of this function you parse the JSON with jQuery.parseJSON(xhr.responseText) and do what you want with this data. It seems complicated, but in fact it is simple.

Upvotes: 1

Related Questions