Reputation: 1712
Having one of those 'I'm clearly doing something wrong' moments. It feels like I'm trying to do something basic, and fighting the framework, so I'm appealing for help!
I'm using Rails 3 and am a bit confused about how to make a search form that results in pages with clean URLs.
My application allows you to search from routes from any location to another location.
For example, a valid URL would be /routes/A/to/B/, or /routes/B
My routes.rb:
match 'routes/:from/to/:to' => 'finder#find', :as => :find
match 'routes/find' => 'finder#find'
My search form:
<% form_tag('/routes, :method => 'post') do %>
<%= label_tag(:from, "From:") %>
<%= text_field_tag(:from) %>
<%= label_tag(:to, "To:") %>
<%= text_field_tag(:to) %>
<%= submit_tag("Go") %>
<% end %>
Controller:
class FinderController < ApplicationController
def index
end
def find
if params[:from].blank? or params[:to].blank?
render :action => "invalid_results" and return
end
@from = Location.find_by_code(params[:from].upcase)
@to = Location.find_by_code(params[:to].upcase)
if @from.nil? or @to.nil?
render :action => "invalid_results" and return
end
@routes = Route.find_all_by_from_location_id_and_to_location_id(@from, @to)
end
end
When I use :method => 'get'
in my form_tag
, the application works, but the URL is hideous. And, of course, with :method => 'post'
, the variables are no longer visible which is bad for bookmarking. How do I tell Rails to use my pretty URLs after POSTing the form?
I am VERY new at Rails so your patience is appreciated.
Upvotes: 2
Views: 3707
Reputation: 12749
Your routes are given an automatic named path that you can see by typing rake routes
. For example:
new_flag GET /flags/new(.:format) {:action=>"new", :controller=>"flags"}
You can refer to the path by using new_flag_path
or new_flag_url
Your form_tag
entry is kinda screwy. Instead of having a separate find
method you could also use the index
method, but that's your choice.
You may find it easier to use a standard redirect_to
to redirect to a prettier URL based on inputs. If you don't want the redirect, then you'll need to use jQuery to change your form's action method dynamically. Searches typically use ugly GET parameters.
So I would change your code to look like this:
routes.rb
get 'routes/:from/to/:to' => 'finder#routes', :as => :find_from_to
post 'routes/find' => 'finder#find', :as => :find
_form.html.erb
<% form_tag find_path, :method => :post do %>
<%= label_tag(:from, "From:") %>
<%= text_field_tag(:from) %>
<%= label_tag(:to, "To:") %>
<%= text_field_tag(:to) %>
<%= submit_tag("Go") %>
<% end %>
finder_controller.rb
class FinderController < ApplicationController
def index
end
def find
if params[:from].blank? or params[:to].blank?
render :action => "invalid_results" and return
end
@from = Location.find_by_code(params[:from].upcase)
@to = Location.find_by_code(params[:to].upcase)
if @from.nil? or @to.nil?
render :action => "invalid_results" and return
end
redirect_to find_from_to_path(@from, @to)
end
def routes
@routes = Route.find_all_by_from_location_id_and_to_location_id(params[:from], params[:to])
end
end
Upvotes: 5