rails: avoid string escaping in route parameters - ruby-on-rails

i have a route defined like this
map.search_by_key '/search/:search_key', :controller => 'my_controller', :action => 'my_action'
the param :search_key is used such that the urls are like this:
mysite.com/search/c_vehicles/c_cars/mk_suzuki
where search_key would be "c_vehicles/c_cars/mk_suzuki" ..
problem is .. when creating this url with the named route
search_by_key_path("c_vehicles/c_cars/mk_suzuki") it escapes the string .. and creates something like:
mysite.com/search/c_vehicles%2Fc_cars%2Fmk_suzuki
this works fine but looks ugly in the address bar .. how do i avoid this ..
I'm using rails 2.2.2 with ruby 1.8.6 (ancient i know .. in process to upgrade) ..
ideas?

You can use a globbed route for this and a bit of string wrangling in your controller:
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
map.connect 'photo/*other', :controller => 'photos', :action => 'unknown'
This route would match photo/12 or /photo/long/path/to/12 equally well, creating an array of path segments as the value of params[:other].
Your route should look like this:
map.search_by_key '/search/*search_key', :controller => 'my_controller', :action => 'my_action'
#--------------------------^ Change the colon to an asterisk
And then in your controller:
def my_action
search_for = params[:search_key].join('/')
# ...
end
The same globbing technique applies equally well in Rails-3 so upgrading this part of your application should be a simple matter switching to the new routes.rb methods.
This works with 2.3.8, I'm not sure about 2.2.2 though.

Related

Escaping elements in a URI Ruby On Rails

I have a rails app that I am trying to do a get request with co-ordinates in...
I have a route in my routes.rb like this:
map.connect 'feeds/get/:location', :controller => "feeds", :action => "get"
I can send a string consisting of alphanumeric characters fine, but I need to send co-ordinates in a string in the URI as a get request:
51.896834,0.878906.
So, I escaped the string like so, and append it to my URI.
http://thisisnottheurl.net/feeds/get/51%2E896834%2C0%2E878906.xml
however it looks like rails automatically unescapes the string before the controller and gives me this routing error in the log:
ActionController::RoutingError (No route matches "/feeds/get/51.896834,0.878906.xml" with {:method=>:get}):
How do I stop rails escaping this string (with routes?) so that it can be read in the controller?
I looked at using the match function in routes.rb with regex, but that is rails 3 only...
The only real way I can think of doing this would be as follows, give the route a name as follows:
map.connect 'feeds/get', :controller => "feeds", :action => "get", as: 'get_feeds'
Then you would have a named route helper get_feeds_path, which you could then pass in location and a format as follows:
get_feeds_path(:location => '51.896834,0.878906', :format => 'xml')
What might be an even better idea however, is if you passed in two params, one for each of the coordinates.
get_feeds_path(:x_location => '51.896834', :y_location => '0.878906', :format => 'xml')
Then, the params hash passed to the controller should have a params[:x_location] and a params[:y_location] which you can manipulate to your liking.

Github like routes in Rails

Using github like chain routes in rails
I have URLs similar to this:
'localhost:3000/document_managers/[:module_name]'
'localhost:3000/document_managers/[:module_name]/1/2/3/.' # can be any level deep
Here is the route definition for them:
map.connect '/document_managers/:module',
:controller => "document_managers",
:action => :new_tree,
:module => ["A","B","C"]
map.connect '/docuemnt_managers/:module/*path',
:controller => "document_managers",
:action => "new_tree",
:module => ["A","B","C"]
Here is the problem:
The idea that module name value can't be anything except from the
given above array i.e("A","B","C") like at any time the URL must be something like
localhost:3000/document_managers/A/1 or
localhost:3000/document_managers/B/221/1 or
localhost:3000/document_managers/C/121/1
but that not the case even though
localhost:3000/document_managers/D/121/1 is treated as valid url
and module is set to D even though the "D" is not in listed array
above
I want the the URL localhost:3000/document_managers/A to
also redirect to same action i.e new_tree if the extra parameter isn't
provided as in the URL contain extra parameters
localhost:3000/document_managers/C/121/1 then the URL is redirected
appropriately to the desired controller and action but if the URL only
contain the path until the module name the Rails return a routes
ActionController::UnknownAction I don't know why as I have already
defined the controller and action.
In Rails 3.1, you can do this in your routes file to get what you want:
match '/document_managers/:module',
:controller => "document_managers",
:action => :new_tree,
:constraints => {:module => /[ABC]/}

Ruby on Rails wildcard routing such as /foo.htm /foo.php /foo.something

I'm trying to create a routing situation where by default, any URL's such as this:
/foo
/something
/foo.php
/somethingelse.xml
/something.something.else
etc.
will all route to one controller, assuming they don't route anywhere else.
i can get this to work with the following code in my routes:
map.myroute '/:file_or_folder', :controller => 'mycontroller'
this works fine as long as there are no dots in the URL:
/something
but this wont work:
/something.foo
any ideas?
Dots are not allowed by default. You can specify a regex for what file_or_folder can match, such as this:
map.myroute '/:file_or_folder', :controller => 'mycontroller', :file_or_folder => /.*/

Ruby on Rails: Routing for a tree hierarchy of places

So we've got a legacy system that tracks places with IDs like "Europe/France/Paris", and I'm building a Rails facade to turn this into URLs like http:// foobar/places/Europe/France/Paris. This requirement is not negotiable, the number of possible levels in unlimited, and we can't escape the slashes.
Setting up routes.rb for http://foobar/places/Europe is trivial:
map.resources :places
...but http:// foobar/places/Europe/France complains "No action responded to Europe". I tried:
map.connect '/places/:id', :controller => 'places', :action => 'show'
...but this gives the same result, as apparently the :id ends at the first '/'. How do I make the ID cover anything and everything after the "places"?
Have a look at the Routing Guide for full documentation:
http://guides.rubyonrails.org/routing.html
Specifically section "4.9 Route Globbing".
But I think what you really want to do is declare your route like:
map.connect '/places/*id', :controller => 'places', :action => 'index'
Called with a URL like
/places/foo/bar/1
Yields a params[:id] => ["foo", "bar", "1"]
Which you could easily (re)join with "/" to yield the full string you want "foo/bar/1" (you will probably have to re-insert the leading slash manually.
That should get you going.
I tweaked Cody's answer above slightly to come up with this:
map.place '/places/*id', :controller => 'places', :action => 'show'
map.connect '/places/*id.:format', :controller => 'places', :action => 'show'
By using map.place instead of map.connect, Rails knows what resource we're dealing with and generated place_url, place_path etc helpers correctly.
Now, the 2nd line should work but doesn't thanks to the bug above, so here's a workaround for places_controller.rb that manually splits the ID and sets the format, defaulting to XML:
id, suffix = params[:id].join('/').split('.')
params[:format] = suffix ? suffix : "xml"

Optional path prefix persistence, using Sven Fuchs' routing filter

I made my routes recognize optional path prefixes, but now I want route generation to remember them without me specifying them each time. I'm using the solution presented here:
Creating routes with an optional path prefix
Here are some examples:
Let's say I'm here: { path => "/", :contoller => 'welcome', :action => 'index', :locale => 'en' } then route generation works like this:
events_path #=> "/en/events"
event_path(1) #=> "/en/events/1"
This is exactly what I want, and everything's great.
Now let's consider I'm here: { path => "/fr", :contoller => 'welcome', :action => 'index', :locale => 'fr' } then route generation works like this:
events_path #=> "/en/events"
events_path(1) #=> "/en/events/1"
This is not helping me at all. What it would be natural to have is events_path to remember params[:locale] and generate "/fr/events". Is there any way I can achieve this?
Unless I'm misunderstanding what you're saying the desired behaviour is exactly the one I've written routing_filter for :)
Try using the provided locale filter by installing the plugin and simply adding map.filter(:locale) to your routes.
If that does not help, please email me or send me a message on github.

Resources