I am using Angular html5mode so have Rails routing set to redirect all failed requests to root
# Angular catch all to allow page refresh
get '*page' => "home#index"
This works just fine, except when an Angular module requests a missing template (/assets/templates/page.html for example), when it causes an endless loop
How can I tell Rails to catch all routes, except things in /assets ?
I noticed this is quite old, but found it through Google and wasn't happy with the only answer here. Since I worked through this myself I will share my solutions.
Use the format parameter in your route
get "/*path" => "home#index", format: false
Simply disable the format option for the wildcard path so it ignores requests with any format (e.g. css, js, png...)
Use a constraint in the route
get "/*path" => "home#index", constraints: -> (req) { !(req.fullpath =~ /^\/assets\/.*/) }
Specify a constraint option with a simple lambda checking your path value, not the best regular expression but shows the idea I'm going for here...
Personally I use the format parameter in my apps, the constraints option also lets you pass in an object, check out the rails guide for more info -> http://guides.rubyonrails.org/routing.html#advanced-constraints
The routes are evaluated top to bottom, so you can do the following:
# Catch all missing templates
get '/assets/templates/*page' => '/assets/templates/default.html'
# Angular catch all to allow page refresh
get '*page' => "home#index"
Missing templates will be caught by the first statement and all other missing routes will be caught by the second statement
Related
So in our Rails 4.2 application, there is the alchemy_cms gem which requires its routes to be mounted last in config/routes.rb.
SampleApp::Application.routes.draw do
#other routes for the rails app here
# :
# :
mount Alchemy::Engine => '/'
end
We get routes like "/somehacker/routingurl" which then falls out to the Alchemy::Engine to handle, resulting in a default 500 error. If I wanted to do a custom 404 error, then the proper way to do it is to build a custom 404 page and have Alchemy handle the redirect? Otherwise since the Alchemy docs specify that it has to be the last route in config/routes.rb, there won't be a way to add a catchall route to redirect to some kind of error page I assume.
EDIT:
One of the problems is that there are some routes that are like the invalid "somehacker" route above that do need to be parsed by the Alchemy routing engine, such as "/en/us" where "en" is a valid locale. This is why I initially thought to put the route handling in the Alchemy engine's routes file.
If it is difficult for you to configure and use the Alchemy cms gem to redirect unknown routes into a custom defined page, you can use the bellow method to implement the same with a small coding tweak given bellow:
Rails 4.XXX
1. First Method.
(routes.rb)
You can still use a simple get to redirect all unknown routes.
get '*path', to: 'home#index'
If you wish to provide routing to both POST and GET requests you can still use match, but Rails wants you to specify the request method via via.
match "*path" => "home#index", via: [:get, :post]
Remember that routes.rb is executed sequentially (matching the first route that fits the supplied path structure), so put wildcard catching at the bottom of your matchings.
Here you can replace the home#index with any custom path that you defined in you application, also note that it is important to keep this redirection code only at the bottom of routes.rb.
2. You can follow the bellow tutorial on the same problem in a different perspective to solve can be found.
Custom 404 error page with Rails 4
I'm starting to learn rails, and I'm seeing the terminology wildcard routes, but I've seen routes listed both of the following ways:
/a/path/*all', :all => /.*/
and
/a/path/:all
What is the difference between these two route forms?
Have you read the Rails Guide on routing yet? That is a great place to start learning about routing in Rails.
For instance, you will learn that your 2nd code block is not a wildcard route. Instead it matches what the guide above refers to as a Static Segment
You'll also learn that to impose restrictions on a segment as you appear to be attempting in the first code block, you must use the :constraints option, such as this wildcard route, or as the guide above refers to them, Route Globbing
GET "/a/path/*all", :constraints => { :all => /.*/ }
However, the above constraint is redundant since the wildcard *all is going to match .* by default anyway.
I am trying to remove the "catch all" or "default" route from a production rails application. I'm interested in maintaining operation while gathering a log of it's usage so that I can replace it with the appropriate hard coded routes.
So, given I have the following default route line in my config/routes.rb file.
match '/:controller(/:action(/:id))'
How could I create or retrieve a log of every time that route gets hit. This log would ideally include only requests actually handled by this route along with parameters and would need to leave the route itself functioning as normal.
Another possibility would be to make use of Rails router constraints option:
match '/:controller(/:action(/:id))', constraints: -> (req) {
Rails.logger.info("Default route used: #{req.path.inspect}")
true
}
Note: the lambda returns true so that the match succeeds.
One way you can do this is the change the default route to:
match ':controller(/:action(/:id))(.:format)', :using_default_route => true
Then put the following function into app/controllers/application_controller.rb
before_filter do
if params[:using_default_route]
logger.info("Default route for #{request.path.inspect}. params = #{params.inspect}")
end
end
I just switched to rails not long ago and I'm loving it. Everything works well in my rails 3.1 application, but now at the end I want to somehow handle routes like www.myapp.com/something (off course, I dont have something controller). I get a routing error when I visit this page, but I was wandering if there was a way to do something about it, even if it's only redirecting these routes to my root_url. I tried to find the answer online with no luck.
Yes, you can put a globbing route at the very end of your routes.rb to catch all misses:
match '/*paths', :to => 'some_controller#some_action'
in your Controller / action you can access the globbed path with
params[:paths]
more information http://guides.rubyonrails.org/routing.html#route-globbing
of course you can redirect without using an extra controller by using the redirect inline rack endpoint
match '/*paths' => redirect('/')
I have some touble with redirect 301 in my new app. I have to redirect some old urls into the new one.
I entred in my routes file this
match "/traslochi_puglia/index.htm", :to => redirect("/preventivo/90-traslochi-in-puglia")
and it works fine, but I can't understand why this
match "/trasloco_casa_abitazione.htm", :to => redirect("/3-trasloco-casa")
does not work. All the old urls with this pattern "/some_path/page.htm" works fine but not "page.htm". Any hint?
Thanks
If you want us to troubleshoot the specific issue you've outlined in your question, we need to see your entire routes.rb file. Without this information, my first guess is this:
The typical route pattern is /controller/action or /controller/:id/action or some combination thereof. With the pattern you've shown above, and assuming you have no named routes in your routes.rb file, then the route you've provided would point to a controller, but not an action. Therefore your app wouldn't know what action to execute, unless you've specifically created a route called /3-trasloco-casa which looks to me more like a URL to a specific resource, than an action on a controller.
Getting to the source of routing issues can most easily be done with a combination of running rake routes at the command line (which shows you the list of route patterns your app will recognize), and then going further by troubleshooting with route recognition, as outlined in this answer to this question:
Recognize routes in rails console Session