How to make Ajax calls with Rails 3 using remote_function?

I am trying to make an onchange call on a select box.For my application i am using jquery.js and rails.js as mentioned to make use of UJS. But still the code that is generated is for Prototype and not for jquery ajax calls. My code looks like the following:

<%= select_tag :category, 
       options_for_select(
           Category.find(:all,:select=>"name,id").collect{|c| [c.name,c.id]}),
       :onchange => remote_function(:url => {:controller => "posts", 
                                             :action => "filter_post",
                                             :filter =>"category"}, 
                                    :with=>"'category_id=' + $('#category').val()") %>

The code that is generated by this is:

new Ajax.Request('/posts/filter_posts?filter=category', {asynchronous:true, evalScripts:true,
parameters:'category_id=' + $('#category').val() + '&authenticity_token=' +
encodeURIComponent('CCyYj1wqXtddK6pUV6bAxw0CqZ4lbBxDGQHp13Y/jMY=')})

Answers


As Sergei said: There is no remote_function in rails 3.

The solution is to unobtrusively add the onchange handler using something like:

$(function($) {
    $("#selector_for_element").change(function() {
        $.ajax({url: '<%= url_for :action => 'action_name', :id => @model.id %>',
        data: 'selected=' + this.value,
        dataType: 'script'})
    });
});

This will call the action_name method in the current controller, passing the result of selected=... as a parameter. Now you can return a piece of javascript, for instance using something like:

calculated = calculate_some_value_using(params[:selected])
render(:update) {|page|
  page << "$('#selector_for_field_to_update).html(#{calculated})"
}

in the controller. The string you append to ''page'' should be valid javascript and will be executed automatically if you use $.ajax.

EDIT: FYI, we recently added a select change helper to jquery-ujs, so you can do this unobtrusive way using the built-in jquery-ujs adapter now:

<%= select_tag :category_id, 
   options_for_select(
       Category.find(:all,:select=>"name,id").collect{|c| [c.name,c.id]}),
   :data => { :remote => true, :url => url_for(:controller => "posts", 
                                         :action => "filter_post",
                                         :filter =>"category") } %>

Though to be fair, adding a select change event really isn't ever going to be "unobtrusive" as there is no graceful fallback for users with javascript disabled unless your form doesn't depend on the result of the AJAX request.


There is no remote_function in rails 3. If you're using jQuery, you can do something like this:

$.ajax({
    type: 'POST',
    url: 'http://your_url/blah',
    data: 'param1=value1&params2=value2',
    success: function(data){eval(data);}
});

Following is the simple jQuery snippet from my haml view

:javascript

    $("#select_box_id").change(function() {
      $.post('#{target_url}?param_one='+$(this).val());
    });

Hope this helps. Thanks..


If you face the issue that I had of upgrading a large rails app to rails 3 that made heavy use of remote_function, you can achieve limited backwards compatibility by adding a application_helper method that generates jQuery code in the format suggested by other answers here. I was able to use this code as is, though had to update one piece of calling code to use the new :success script option instead of the :update hash option that is not supported here. This can buy you some time to eventually refactor all remote_function calls to use unobtrusive jquery-ujs event callbacks:

def remote_function(options)
    ("$.ajax({url: '#{ url_for(options[:url]) }', type: '#{ options[:method] || 'GET' }', " +
    "data: #{ options[:with] ? options[:with] + '&amp;' : '' } + " +
    "'authenticity_token=' + encodeURIComponent('#{ form_authenticity_token }')" +
    (options[:data_type] ? ", dataType: '" + options[:data_type] + "'" : "") +
    (options[:success] ? ", success: function(response) {" + options[:success] + "}" : "") +
    (options[:before] ? ", beforeSend: function(data) {" + options[:before] + "}" : "") + "});").html_safe
end

Ajax Call to controllers-action with parameters:

function combined_search() {
    var countries = $('#countries').val();
    var albums = $('#albums').val();
    var artists = $('#artists').val();
    $.ajax({
        url:"<%=url_for :controller => 'music_on_demand',:action => 'combined_search' %>",
        data:'country=' + encodeURIComponent(countries) + '&albums=' + encodeURIComponent(albums) + '&artists=' + encodeURIComponent(artists),
        cache:false,
        success:function (data) {
        }
    })
}

Need Your Help

networkx draw graph deprecated message

python-3.x networkx

I am trying to draw a graph networkx using python 3.6 with Jupyter notebook and the network package with anaconda. But the graph is not drawing per the documentation, I am just getting a deprecated

Is it possible to define a generic lambda in C#?

c# c#-3.0 lambda

I have some logic in a method that operates on a specified type and I'd like to create a generic lambda that encapsulates the logic. This is the spirit of what I'm trying to do: