Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using named routes with parameters and form_tag

I'm trying to create a simple search form in Rails, but I think I'm missing something.

I have a named route for search:

map.search ":first_name/:last_name", :controller => "home", :action => "search"

I'm trying to use that in my search form:

<% form_tag(search_path, :method => 'get') do %>
  <%= text_field_tag(:first_name) %>
  <%= text_field_tag(:last_name) %>
  <%= submit_tag("Search") %>
<% end %>

But when I load up the search form I get an ActionController::RoutingError:

search_url failed to generate from {:action=>"search", :controller=>"home"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: [:first_name, :last_name] - are they all satisfied?

What am I missing? I thought the fields defined in my form would be automatically linked up with my route parameters. :-/

Update:

I understand that search_path is generated before the form is displayed now, so it can't be updated. Obvious in hindsight!

I changed my routes:

map.search 'search', :controller => "home", :action => "search"
map.name ':first_name/:last_name', :controller => "home", :action => "name"

And now the search action just does:

def search
  redirect_to name_path(params)
end

It all works a treat! The main goal here was getting that URL from the name named route as result of doing a search. Thanks guys!

like image 721
Stewart Johnson Avatar asked Jan 30 '10 12:01

Stewart Johnson


2 Answers

form_for generates form and it has to have specified all parameters that are needed to create search_path, so it should look like:

<% form_tag(search_path, :firstname => 'some_text', :lastname => 'some_text', :method => 'get') do %>

or at least something like this. HTML tag form has parameter action='/some/url' and that's why you have to specify all parameters for search_path. But the above example won't work as you expected.

So what you can do?

  1. Create empty form that has action='/' and with js replace it with content of your input text fields before submitting.

  2. Create another route, on example /search that recives parameters from submit and then redirects to correct path.

Probably there is also some better ways to do it ;)

like image 97
klew Avatar answered Oct 13 '22 12:10

klew


First, search_path is actually a method, which takes a hash of options. It is this method which should receive :first_name and :last_name.

Second, a browser can only submit form parameters as the body of a POST request, or as query string parameters (for any kind of request method). So there's unfortunately no way a browser's native submit function can generate that kind of URL.

Another way of thinking of it: What you're doing here is filling the form tag's action attribute with an URL. Rails needs a complete URL as you're building the form. So all parameters in your route need to be specified when the form helper is called, rather than at the next POST request.

So unfortunately, what you're trying to do is not possible in a normal Rails application.

(If you really want to, you might be able to pull it off by writing your own form helpers and a bit of Javascript to replace the browser's native submit function. The Javascript would then construct that URL based on the form fields. I'd argue against it, though.)

like image 37
Stéphan Kochen Avatar answered Oct 13 '22 12:10

Stéphan Kochen