views:

30

answers:

1

I try this:

remote_function(:url => {:controller => '/cities', :action => 'show'}, :method => 'get')

But I get a routing error because I didnt specify an ID. But I want the ID to be able to change depending on a value that the user selects on the page at runtime. So then I tried this:

remote_function(:url => {:controller => '/cities', :action => 'show'}, :method => 'get', :with => "'id=' + $F('query_city_id')")

But this also gives me a routing error, I guess because it wants me to define :id in the :url in order to generate a valid url to 'show' a city. So I try to hardcode a "1" for :id, just to make it go, and then overwrite :id in the :with:

remote_function(:url => {:controller => '/cities', :action => 'show', :id => 1}, :method => 'get', :with => "'id=' + $F('query_city_id')")

But that also does not work. It seems what I'd really want is something like this:

remote_function(:url => {:controller => '/cities', :action => 'show', :id => "$F('query_city_id')"}, :method => 'get')

But I know that does not work. Can someone point me in the right direction? I maybe trying to use the wrong remote function, or I might need to do something more Rails 3-like, or I may really need to generate the underlying ajax call dynamically on the client side at runtime.

A: 

So for your route, the :id is present, right? That's why you have to provide the id when you generate your route.

You could overwrite the route so that it contains no :id, or set :id as optional (use (:id), and then append your id as param to send.

However I haven't used remote_function before :D

===== UPDATE =====

So I'm really not familiar with remote_function as I seldom use the built-in prototype, but jquery.

It seems like you are giving a list of city id for choose, then pass the id to the sever to get the city, and display it on the page.

The following is just an example, might not suit you case:

Define the route:

map.ajax_show_city "/cities/:id", :controller => "cities", :action => "show"

In CitiesController

def show
  @city = City.find(params[:id])
  respond_to do |format|
    format.html #if you don't like, you could delete this line
    format.js # auto call cities/show.js.erb
  end
end

In cities/show.js.erb

jQuery("#the_place_you_want").append("<%= javascript_escape(render(:partial=>@city)) %>");

The render would use cities/_city.html.erb to give the city html code

<%= select_tag "cities", cities_options(with_id_as_the_option_value), :onchange => "show_city(this, '#{url_for(ajax_show_city_path)}')" %>
# This will generate something like:
<select name="cities" id="cities" onchange="show_city(this, '/cities')"> # note the path generated
  <option value="1">City 1</option>
  <option value="2">City 2</option>
</select>

The js function needed:

function show_city(select, link) { # sorry for using jQuery
 $.post(link + "/" + retrieve_option_value(select), "", null, "script");
 # $.post(link_to_post, addintional_data, handling_function_after_success, request_type)

 # This would post to /cities/2 with no any params added.
 # Due the the request type being set to script, the returned data would be treated as javascript and executed. So no handling function is needed (that's why null)
}

function retrieve_option_value(select) {
  $(select).children(":selected").val(); # just get the selected option's value
}

That's all.

So if the js is switched off, the user could still press the submit button (use js to hide or detach the button) and get proper result! Adding js is just adding more fancy things. Of course, I agree that almost everyone won't turn off their js support. But it's the accessibility to the disables.

=====

It's quite tricky that for resource's show path, it seems you must provide an id in order to generate the path without error.

you could test the routes:

map.connect "/test", :controller => "cities", :action => "test" # for test only

map.resources :cities
map.other "/cities/show/:id", :controller => "cities", :action => "show", :method => :get

def test
  render :text => url_for(city_path)     # ambiguous routes error
  render :text => url_for(city_path(0)   # gives /cities/0
  render :text => url_for(other_path)    # gives /cities
  render :text => url_for(other_path(0)) # gives /cities/0
end

A workaround for your way is to generate /cities/0 and in runtime use js to replace 0 by your selected id.

PeterWong
Well then what are you using to make remote calls from a page? This seems like something very common that any Rails app would be doing. It's nothing fancy, but I'm having a hard time keeping it RESTful and making a remote call... I dont want link_to_remote, and I dont want to submit a remote form. What are my other options? Do I need to move to JQuery and Uobtrusive Javascript? I can't find good info on this with UJS and JQuery, can you point me towards a good link?
Buddy
Actually I am using jQuery. I usually built the site without any AJAX call first so that it works even when javascript was disabled or screen readers. After that I use javascript to make form submit uses AJAX (so won't be affected if javascript disabled). Making a form to submit by AJAX could simply by attaching generic a function to onsubmit event. `$(".turn_me_to_ajax").live("submit", submit_with_ajax);` and `function submit_with_ajax() { $.post($(this).attr("action"), $(this).serialize(), null, "script"); }`. Simple ^^
PeterWong
First of all, I dont care about users with javascript disabled. If they dont have JS, then they might as well not even bother trying to do anything on the internet. And I dont care about screen readers. You are describing a remote form submission with JQuery, which is not what I am after. Of course I know how to submit a remote form, it is simple. I need to call a remote function from a page. If you aren't doing this, then your sites must be very boring and simplistic!
Buddy
I think submitting ajax form is just similar to calling remote function (if remote function is also kind of ajax calls). So what you are going to do is just by ajax send the `id` to the server and then update the current page, right? By using the `respond_to`, you could give current page updating javascript! Please see my update (currently writing, please wait.)
PeterWong