Parameter name and value (independently) as part of the Rails route

DocumentsController # common_query can handle several different query styles.

i.e. all documents in batch 4 or all documents tagged "happy"

I need one route to make em pretty, like so:

/ docs / common_query? Batch = 4

/ docs / common_query? Tag = happy

become:

/ Documents / parties / 4

/ documents / tags / happy

So the end result is that #common_query is called, but the url part was used as the parameter name and its part as the value.

+1


source to share


2 answers


As one route:

ActionController::Routing::Routes.draw do |map|
  map.connect "documents/:type/:id", :controller => "documents_controller", 
              :action => "common_query"
end

      

Then it params[:type]

will be either "batch"

, or "tag"

, and params[:id]

either "4"

, or "happy"

. You will need to make sure the other actions for DocumentsController

go before this in the routes, because this will match any url that looks like "documents/*/*"

.



But why should this be the only route? You can use two routes:

map.with_options(:controller => "documents_controller", 
                 :action => "common_query") do |c|
  c.connect "documents/batch/:page", :type => "batch"
  c.connect "documents/tag/:tag",    :type => "tag"
end

      

which will have the same effect, but more specific, so you don't have to worry about the priority order of the routes.

0


source


The second option with two routes is by far the best way, because it will only match the URLs you want to support, while the first option will also match URLs like / documents / foo / bar , which will most likely result in your #common_query method returning a RecordNotFound (404) response at best. In the worst case, if you are not prepared not to see any expected parameters, you will get 500 errors instead ...

Of course, if you have many variations, you will have many routes. And if you need to use them in combination, for example / documents / batch / 4 / tag / happy, then you will need to use a wildcard and do the parameter handling in your controller. It might look something like this:

map.connect 'documents/*specs', :controller => "documents_controller", :action => "common_query"

      



The various elements of the URL will be available to your controller as parameters [: specs]. You can turn it into a find like this:

@items = Item.find(:all, :conditions => Hash[params[:specs]])

      

This Hash [] technique converts a one-dimensional array of parameters into a hash value of the key, which can be useful even if you don't feed it directly into find ().

+1


source







All Articles