Detecting multiple subfolders in Routes.rb - ruby-on-rails

I want to match the following URLs to the same controller in my Rails app
/controller/folder1/folder2/
/controller/folderA/folderB/somefile
/controller/folderX/somefile
I currently can achieve the desired result if I limit the number of nested folders like so in my Routes.rb:
match '/controller(/:folder1)(/:folder2)(/:file)' => 'myspecial_controller#myaction'
Please note that the following does not work and an URL with multiple path components is not matched:
match '/controller/:full_path
I am wondering if there is some type of wildcard. So that I would ideally get an array of the path components that I can then assemble in the controller.

From documentation
match '/controller/*full_path'

Related

Change the generated EDIT routes in Rails 3.2 to put id _after_ `edit`

As well explained in the Rails Guide on Routing, a resourceful route declaration like
resources :photos
generates a suite of routes and helpers. One of the routes is
/photos/:id/edit
and along with it comes the helper edit_photo_path(photo) which takes a photo object and returns the path to use to edit it. I use the helpers everywhere and want them to keep working as-is.
Well, for various reasons, this one application is generating custom IDs and it is possible for an ID to look like 64/edit or look like 64. This of course causes problems, because regardless of constraints or tweaks
/photos/64/edit
either gets interpreted as #edit 64 or #show 64/edit and neither one is always right.
The solution I would like to implement is to keep all the benefits of resourceful routers, in including being able to pass objects into the path helpers, and just change the Rails default edit path to be
/photos/edit/:id
Then all the paths would be unambiguous. Is there a (reasonably simple and clean) way to do this?
Note
I have a workaround in place so please do not provide workarounds.
Any solution must update the helpers so that edit_photo_path(photo) produces /photos/edit/:id and also works with nested resources. For example, edit_magazine_photo_path(#magazine, #photo) would produce /magazines/:magazine_id/photos/edit/:id.
I have multiple resources, so I'd prefer not to explode the size of my routes.rb with special overrides.
I know I can change the path name of the edit portion using the path_names option. (This is, in fact what I did, putting a Unicode character that will never appear in the ID in the renamed edit path, but now I have the users seeing Unicode URLs, which I don't like, and this will fail once IDs get expanded to Unicode strings.)
I know I can write custom match rules, but that gets very tedious and difficult with nested resources, particularly when it comes to generating path helpers that take objects.
I read the answer to the question "Remove the edit suffix to url" but that answer does not, in fact, remove the edit suffix, it changes a different part of the URL.
I really want insight into the inner workings of the resourceful route generation, especially the URL helpers, so that I can just switch the order of edit and id in the path.

Regex to match nested show path

I'm trying to write a regex to match a show path of a nested resource. The path goes like this: /users/:user_id/products/:id - I have been unable to write a regex to check if a url is for this path. I don't want anything after the products/:id to pass the match. Right now I have the following:
/users/([^&]*)/products/
This works in that it'll match the url path I'm looking for, but I cant figure out how to end it after the /products/:id so it won't match actions such as /edit. So users/1-my-name-is-bob/products/1-awesome-product should match, but users/1-my-name-is-bob/products/1-awesome-product/edit should not match the regex.
try to use this pattern:
\/users\/([^&\/]+)\/products\/[^\/]+\Z
\Z stand for end-of-the-string
you can remove slashes at the begining if not needed, or make it optional with a question mark

Matching all .html files to High Voltage in Rails

How do I match all .html files with High Voltage's controller in Rails so that any url with .html at the end opens the corresponding pages/<page>.html.erb file in my views directory? And of course then I can reference it with High Voltage's page_path named route?
I don't think it's possible, or at least trivial. The "suffix" part of the URL is mapped to the format of the request, e.g., /pages/document.html, /pages/document.json, /pages/document.xml, /pages/document.csv, etc. That is fundamental to Rails routing, and .html is the default format, so /pages/document will, by default, return HTML. It might be possible to create a route such as:
match '*.html' => 'high_voltage/pages#show', as: :static
I have not tested it though.
If you put the match at the bottom, it might be the case that even if the incoming url has .html on it, it will match something else before. Conversely, if you put it at the top, it might match everything that does not have a suffix. Should be easy enough for you to test it.
My high voltage route:
get '/:id' => 'high_voltage/pages#show', as: :static
is at the bottom of my routes, right before the root url, so it's basically the catch all. As long as my static html file paths are distinct from my RESTful routes, it works fine.
Otherwise, if it's acceptable for those static URLs to redirect (permanent), you could put the match in the upstream HTTP server, like nginx or apache, and redirect it to a known high voltage path, like /pages.

Cakephp url customisation for SEO

I am developing a medical products search site. I need to display my site in search engines whenever a user try to search [COMPANY NAME] medicine [DISEASE]. For this, i created a page in my site which reads COMPANY NAME and DISEASE from url and lists all products.
Now i need to give this page a url like www.sitename.com/[COMPANY NAME]_medicine_[DISEASE].html
I am using Cakephp framework for development. Is there anyway to implement this url formatting in routes.php ? Or is there any other way ? please help.
how about separating them with slashes?
// www.sitename.com/[COMPANY NAME]/medicine/[DISEASE]
Router::connect('/:company/medicine/:disease', array('controller' => 'diseases', 'action' => 'index'),
array('pass'=>array('company','disease'),
'company'=>"[a-zA-Z\.]+*",
'disease'=>'[a-zA-Z\.]+'));
and the controller
function diseases($company,$disease){
}
I'm not sure if you can use the underscore instead of the slashes, I have never tried it before. if you do try I'd like to know the results =)
Good Luck
EDITED: ok, i was too curious about this issue and i wrote a route like this
Router::connect('/:company_medicine_:disease', array('controller' => 'pages', 'action' => 'test'),
array('pass'=>array('company','disease'),
'company'=>'[a-zA-Z]+',
'disease'=>'[a-zA-Z]+'));
and its not working u_U
as i suspected, the problem is that Cake thinks that the name of the custom route element is :company_medicine and not :company.. after a few minutes regarding/reading the code of Cake i found out the exact place where Cake parses the route and extracts the names of the passed elements. It's in /cake/libs/router.php in the class CakeRoute, method _writeRoute() (about line 1369):
preg_match_all('#:([A-Za-z0-9_-]+[A-Z0-9a-z])#', $parsed, $namedElements);
so as you can see in the regexp, the names of the elements can contain an underscore,therefore Cake thinks the name of the parameter is ":company_medicine".
So you have four solutions:
use slashes as separators for your urls
change the order of your parameter so it would be medicine_[COMPANY]_[DISEASE]
modify the line 1369 of the router.php to this (NOT RECOMENDED, i think it will break routes for plugins):
preg_match_all('#:([A-Za-z0-9]+)#', $parsed, $namedElements);
use url rewrite in your .htaccess to redirect all [COMPANY]_medicine_[DISEASE] to [COMPANY]/medicine/[DISEASE] so cake will see it separated by slashes and the browser will see it separated bu underscores. (I haven't tested it, i've never added another rule to the .htaccess for Cake =P)

How to embed multiple tags in Rails routes, like Stack Overflow

When one selects a tag on Stack Overflow, it is added to the end of the URL. Add a second tag and it is added to the end of the URL after the first Tag, with a + delimiter. For example:
http://stackoverflow.com/questions/tagged/ruby-on-rails+best-practices
How is this implemented? Is this a routing enhancement or some logic contained in the TagsController? Finally, how does one 'extract' these tags for filtering (assuming that they are not in the params[] array)?
Vojto's answer is correct, but note that you can also use Route Globbing on the server side to handle this cleanly. A route defined as /:controller/*tags will match /questions/ruby/rails/routing, and in the questions_controller, params[:tags] will be an array containing ['ruby','rails','routing']. See the Routing docs.
I think Rails doesn't mind if params contains symbols like +. That means, you can access all tags as one argument, create a route like: '/show/:tags'
Then you can access params[:tags], which will be string like 'ruby+rails'. You can simply do 'ruby+rails'.split('+') to turn it into an array.
By that you can easily append new tag to this array, and turn it back into string with my_array_with_tags.join('+').

Resources