Route in rails with simple regex doesn't match - ruby-on-rails

I looked on the web for a while but I can't get this to work. Our application has to work with urls like ourapp.com/meandyou, where the common element is the "and" in the parameter.
I saw that it's possible to constrain urls parameters using regex, so I added the rule to routes.rb, but without success. If I try to match the same expression using the terminal, it works. Here's the complete route file:
Railroot::Application.routes.draw do
resources :couples
get "home/index"
root :to => 'home#index'
match ':url' => 'couples#show_url', :url => /and/
end
I read that Rails nests the expression within a bigger one when matching the route, so maybe I'm doing something slightly wrong even for such a simple expression.
I'm running on Ubuntu 10.04, Ruby 1.9.3, Rails 3.2.3, Passenger 3.0.13, Nginx 1.2.1.
Thanks in advance for your help!

This should be your starting point:
Railroot::Application.routes.draw do
root :to => 'home#index'
resources :couples
match ':url' => 'couples#show_url', :constraints => { :url => /and/ }
end

This may be your answer, from the rails routing docs:
:constraints takes regular expressions with the restriction that regexp anchors can’t be used. [...]
However, note that you don’t need to use anchors because all routes are anchored at the start.
So I think what you are actually matching against is not /and/ but /^and/, which would explain why it's not working.
Try being more explicit, like this:
match ':url' => 'couples#show_url', :url => /.*and/

Related

Rails 4: You should not use the `match` method in your router without specifying an HTTP method

Okay, so I've upgraded to Rails 4 (kind of unplanned with my 10.9 server update) and have been able to get everything running on my photo gallery app except for the routes. For some reason I've always had trouble understanding routes since rails 3. Here was my previous working code under Rails 3
root :to => "gallery#index", :as => "gallery"
get 'gallery' => 'gallery#index'
resources :galleries
match 'gallery_:id' => 'gallery#show', :as => 'gallery'
I understand that match has been depreciated, but if I try to use GET, I'm getting the following error:
Invalid route name, already in use: 'gallery' You may have defined two routes with the same name using the :as option, or you may be overriding a route already defined by a resource with the same naming.
Basically, I want the root (index) to load as "/photos/gallery" as it does, and my show action to load, for example, record id 435 as: "/photos/gallery_435" which is how I previously had it working. Sorry for what is probably a simple question, I just cannot seem to grasp the rails routing.
Try this
match 'gallery_:id' => 'gallery#show', :via => [:get], :as => 'gallery_show'
You can then refer to this path as gallery_show_path in your helpers and views.
Changing the 'as' removes the conflict.

Making Rails Resource and Custom Routes Conflict Work

I am new to rails and was wondering how I can make this work. I want a URL to look like this:
http://localhost:3000/businesses/coldfire-gundam
using this route:
match "/businesses/:permalink", :to => "businesses#show", :as => :business_permalink
however when I place this route before this:
resources :businesses
any call to /businesses/1 (1 as param[:id]) does not work anymore, obviously because it is caught by the permalink declaration
how can I make it work then?
You need a way to differentiate /businesses/:id and /businesses/:permalink. The :id should always be numeric (unless of course you're using MongoDB) so if you can force your :permalink to always contain something non-numeric then a simple :constraints should do the trick:
match '/businesses/:permalink', :to => 'businesses#show`, :constraints => { :permalink => /.*\D/ }, :as => :business_permalink
The /.*\D/ forces the route to only match if :permalink contains at least one non-numeric character. You need the .* because route regexes are implicitly anchored at the beginning.
If you happen to be using MongoDB then your :id will probably be a hex BSON ID so you'd want to use /.*\H/ as your constraint and you'd want some way to ensure that your :permalink always contains at least one non-hex character.
Once all that's in place you can put your match "/businesses/:permalink" before your resources :businesses in routes.rb and everything should work fine. And routes are checked in the same order that they appear in routes.rb so you will want your match before your resources.
I would suggest using the friendly_id gem for creating permalink routes. This will handle most of the 'magic' for you in an easily reusable way.
Resources for the gem and railscast:
https://github.com/norman/friendly_id
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid

Make routes upperscore instead of underscore?

Very basic and maybe I missed it, but instead of doing something like sign_up for my routes, how can I do sign-up? This is assuming I have these route like this:
get "/sign_up" => "devise/registrations#new"
It doesn't work for me if I change it to: get "/sign-up".
Try this instead:
match "/sign-up" => "devise/registrations#new", :as => :sign_up
Unfortunately ActionDispatch works best with underscores. So you might try compromising by keeping with convention for the sign_up_path helper and using the dash in the URL

Rails routes match starting with a numeric character

I have a an url like "http://domain.com/1and2" that I wanted to set up in config/routes.rb like this:
match "1and2" => "frontpage#oneandtwo"
(with controllers and views in place).
Running 'rake routes' outputs 'Invalid route name: '1and2''. This error is apparently triggered when you start a match with a numeric character.
Is there a workaround, or am I doing it wrong?
match '/:id' => "frontpage#oneandtwo", :constraints => {:id => /1and2/}
The root of the problem is that methods in Ruby cannot start with a number. Since Rails routing will generate an accessor method for each route, you'll get an error.
You can pass by the issue by naming your route differently with the :as parameter.
I had an issue where I wanted to redirect from a URI /2012 -- which resulted in an error. I corrected it by adding :as => current_year to the routing:
match "/#{Time.now.year}" => redirect("..."), :as => :current_year
Further information:
https://github.com/rails/rails/issues/3224

ruby on rails - routes.rb - match file extension when multiple periods exist in filename

I have created a route plus controller for doing dynamic css in ruby on rails as per the instructions here:
http://www.misuse.org/science/2006/09/26/dynamic-css-in-ruby-on-rails/
It took some changing to account for a newer version of ruby on rails, but the problem comes in with the routes.rb entry. The original entry was this:
# dynamic CSS (stylesheets)
map.connect 'rcss/:rcssfile',
:controller => 'rcss',
:action => 'rcss'
This did not work with a newer version of RoR, and I found this solution to work:
# dynamic CSS (stylesheets)
map.connect 'rcss/:rcssfile.css',
:controller => 'rcss',
:action => 'rcss'
However, now I was bummed that I couldn't get a catch-all filetype extension handler. The request had to have the .css extension. Playing around with it further I came up with this:
# dynamic CSS (stylesheets)
map.connect 'rcss/:rcssfile.:format',
:controller => 'rcss',
:action => 'rcss'
So this is much better. Now I could potentially request a file that ended in .foobar or whatever and match it with a handler. Not that I would necessarily, but it's more about understanding everything.
So then I tried creating a file that looked something like "foo.net.rcss" . Now it would seem that the first dot messes everything up. "no routes match rcss/foo.net.css". My questions are as follows:
How can I match any filename and any extension regardless of how many dots are in the filename?
Why does the first example not work in later RoR versions?
Why do multiple dots screw up the match?
Thanks in advance for any help.
------- update -------
I am using Rails 3.0.5 . As per some more research I can shorten the syntax to:
match 'rcss/:rcssfile', :to => 'rcss#rcss'
This is the equivalent of the first example that did not seem to work, however using this syntax it works just as expected.
match 'rcss/:rcssfile:.:format', :to => 'rcss#rcss'
This also works just like my previous example #3, however it still has the problem of not matching a file with multiple periods.
It would seem that labeling a standard ":paramater" takes special consideration for the period character. ":parameter" will match a path with up to one period, ":parameter.:extension" will match a path with up to two periods, but the :extension will be only what's between the two periods, etc.
A way around this is to use what is called "Route Globbing", which uses an asterisk instead of a colon:
match 'rcss/*rcssfile', :to => 'rcss#rcss'
The only caveat is that this will match ANYTHING after the asterisk, including subdirectories. As such, you want to make sure that this does not accidentally expose any secure files or accidentally render things unintentionally.
I used this for a general case when you don't know the extension:
get '/uploads/:basename.:extension', to: 'controller#action', basename: /.*(?=\.[\w\d]+$)/
Use a regex to match the filename?
map.connect 'rcss/:rcssfile',
:controller => 'rcss',
:action => 'rcss',
:requirements => {:rcssfile => /.+\.rcss/ }
This would match (anything).rcss - you could adjust the regex for various suffixes.

Resources