Rails redirecting invalid route to root - ruby

If my website is www.foo.com if the user types www.foo.com/blahblahblah it will say that /blahblahblah is an invalid path (obviously). But I want it instead to redirect to the root_path so that the controller can process the URL -- the page www.foo.com should be rendered I want to pull the text blahblahblah and do something with it. How do I do this?

There are several possibilities. Here's one. You could add this to the bottom of your routes.rb:
match ':not_found' => 'my_controller#index',
:constraints => { :not_found => /.*/ }
which will establish a catch-all route to make MyController's index action handle any missing paths; it can detect them by looking at params[:not_found] and doing whatever it wants, such as redirecting to the root_path (redirect_to root_url), redirecting somewhere strategically based on the bad path, rendering something special, examining the referrer/referer for clues about the source, etc.
The :constraints option is necessary; otherwise the not_found param won't be able to contain special characters like slashes and dots.
Put this at the bottom of your routes because, obviously, it will match everything, and you want to give your other routes first crack at the path.
If you only want to redirect, nothing more, you could do this instead (again, at the bottom):
match ':not_found' => redirect('/'), :constraints => { :not_found => /.*/ }

in rails 4
get '*path' => redirect('/')

Related

Problems about placeholders of Netlify redirects

I am trying to set up some URL rewrites in Netlify.
I want to set up a rewrite to redirect
https://example.com/blog/2019/05/15/hello.html
to
https://example.com/blog/2019/05/hello.html
I read the document - https://www.netlify.com/docs/redirects/#placeholders:
You can use placeholders in the origin and target paths:
/news/:year/:month/:date/:slug /blog/:year/:month/:date/:slug
This would redirect a URL like /news/2004/02/12/my-story to /blog/2004/02/12/my-story
And I have my _redirects file like this:
# Redirect old permalinks to new format
/blog/:year/:month/:date/:slug.html /blog/:year/:month/:slug.html 301!
It did work to redirect
https://example.com/blog/2019/05/15/hello.html
to
https://example.com/blog/2019/05/hello.html
But there is a weird problem, it also redirects
https://example.com/blog/2019/05/not-a-date/index.html
to
https://example.com/blog/2019/05/index.html
My question is, Is it able to (if yes, how can I) make the :date placeholder matching day only? not-a-date is not a date obviously, shouldn't :date match 01 to 31 only?
To my knowledge the placeholders aren't typed (allowing only numbers). So anything will match and it's not possible to define only days as a pattern to match.
https://www.healingislands.com/* http://www.healingisland.com:splat 301!
putting { /* } this at the end of the first link and putting { :splat 301! } this at the end just worked for me

Rails routing issue - URL works, though button to link to it won't

I'm writing what is currently a very inelegant program to generate fitness plans, and have an issue with the routing. I want buttons on my index page linking to certain bodyparts and a plan generator, and the pages themselves are working when I navigate to them directly. However, the buttons on my index view won't work, kicking out a routing error: 'No route matches [POST] "/exercises/index"'.
For example, dropping the URL for '/exercises/legs' or '/exercises/generator' into my browser loads the page as it should be, though <%= button_to "Legs", 'exercises/legs' %> (as well as redirecting to exercises_legs_path and every other option I've thought of) gives the error.
Sure this is something pretty straightforward I'm missing (very new to this), and any advice would be great!
The database currently contains columns for the :id, ':move' (i.e. press up) and ':bodypart' (i.e. legs).
Here are my routes:
Helper HTTP Verb Path Controller#Action
GET /exercises/:bodypart(.:format) exercises#bodypart
exercises_generator_path GET /exercises/generator(.:format) exercises#generator
exercises_index_path GET /exercises/index(.:format) exercises#index
root_path GET / exercises#index
exercises_path GET /exercises(.:format) exercises#index
POST /exercises(.:format) exercises#create
new_exercise_path GET /exercises/new(.:format) exercises#new
edit_exercise_path GET /exercises/:id/edit(.:format) exercises#edit
exercise_path GET /exercises/:id(.:format) exercises#show
PATCH /exercises/:id(.:format) exercises#update
PUT /exercises/:id(.:format) exercises#update
DELETE /exercises/:id(.:format) exercises#destroy
And my routes.rb file:
Rails.application.routes.draw do
get '/exercises/:bodypart', to: 'exercises#bodypart'
get '/exercises/generator', to: 'exercises#generator'
get 'exercises/index'
root :to => 'exercises#index'
resources :exercises
end
Thanks in advance, and let me know if there's anything else I've got that would help with this.
Rails.application.routes.draw do
get '/exercises/:bodypart', to: 'exercises#bodypart', as: 'exercises_bodypart'
get '/exercises/generator', to: 'exercises#generator'
get 'exercises/index'
root :to => 'exercises#index'
resources :exercises
end
instead of
Rails.application.routes.draw do
get '/exercises/:bodypart', to: 'exercises#bodypart'
get '/exercises/generator', to: 'exercises#generator'
get 'exercises/index'
root :to => 'exercises#index'
resources :exercises
end
Usage:
exercises_bodypart_path('legs')

URL Rewrite Ruby on Rails

We have a Redmine installation on an old server and moved it to a new one with a new domain. Problem is, we need to redirect urls from the old domain to the new one. I really don't have much knowledge about ruby. I was thinking redirecting URLs on this one is as easy as some rewrite rules with .htaccess but I found it different. I've read some answers here redirect but can't figure out where to put those codes.
The scenario should be like:
from http://www.old-domain.com:3000/issues/3456
should be redirected to http://www.new-domain.com:3000/issues/3456
Can anyone help me how to do this? Or if you have better idea how to achieve this?
I'm planning on reading some ruby guides for the meantime.
Thanks guys!
Update:
I managed to create a simple redirect by doing the following:
I created a controller redirect_controller.rb:
class RedirectController < ApplicationController
before_filter :show
def show
redirect_to "http://www.new-domain.com:3000/", :status => :moved_permanently, :notice => "Notice: A redirect!!!"
end
end
And added this to routes.rb:
map.connect '/', :controller => 'redirect'
But I only managed to redirect the page after a successful login. How can I redirect all pages to the new one retaining parameters such as /issues/3456 if there are any?
You can go to your application.rb file (I found it better than place the redirection in the application controller), which is loaded to start all the rails and all engines. The key here is to use
head :moved_permanently, :location => "http://www.newdomain.com/"
To call that you can wrap it in a method I found in a blog. I added some comment
def perm_redirect_to(options)
url = case options
when String # if you pass a string url, which is your case
options
else
url_for(options) # if you pass some more complex option hash in
# `options`, which doesn't seem to be your case
end
head :moved_permanently, :location => url
end
You can call this method passing your url perm_redirect_to(your_new_url)!

How can I create a Rails 3 route that will match all requests and direct to one resource / page?

I have a rails app (Rails 3.0) that I need to temporarily take out of service. While this is in effect, I want to create a new route that will direct all requests to a single piece of static content. I have a controller set up to serve my static pages.
I tried something like this:
match '*' => 'content#holding'
and
match '*/*' => 'content#holding'
to match a wildcard route as described here:Rails 3 route globbing without success.
This is probably a really simple answer, but I couldn't figure it out.
/EDIT/
Forgot to mention that I did have this rule at the very top of my routes.rb file.
Rails needs to bind the url parameters to a variable, try this:
match '*foo' => 'content#holding'
If you also want to match /, use parenthesis to specify that foo is optional:
match '(*foo)' => 'content#holding'
I did this just yesterday and first came up with the solution that klochner shows.
What I didn't like about this is the fact that whatever you enter in the URL, stays there after the page loads, and since I wanted a catch all route that redirects to my root_url, that wasn't very appealing.
What I came up with looks like this:
# in routes.rb
get '*ignore_me' => 'site#unknown_url'
# in SiteController
def unknown_url
redirect_to root_url
end
Remember to stick the routes entry at the very bottom of the file!
EDIT:
As Nick pointed out, you can also do the redirect directly in the routes file.
I ran into something like this where I had domain names as a parameter in my route:
match '/:domain_name/', :to => 'sitedetails#index', :domain_name => /.*/, :as =>'sitedetails'
The key piece to this was the /.*/ which was a wildcard for pretty much anything. So maybe you could do something like:
match '/:path/', :to => 'content#holding', :path=> /.*/, :as =>'whatever_you_want'
Where in "routes.rb" is this line located?
To have priority over other routes, it has to be placed first.
As an alternative, you can look into this: http://onehub.com/blog/posts/rails-maintenance-pages-done-right/
Or this: Rails: admin-only maintenance mode

Expiring all caches on a controller

I got a resourceful controller with a custom action. The action is pretty heavy, so I'm working on caching it:
class MyController < ApplicationController
caches_action :walk_to_mordor
# GET /my/:id/walk_to_mordor/:direction
def walk_to_mordor
# srz bzns
end
end
It works very nice, caching is done and the page is now fast. However, I want to allow the user to "bust" the cache by clicking on a link on the page. At first I tried:
def bust_cache
expire_action :action => :walk_to_mordor
end
Rails complained that no route matches my action. Might be because of the parameter. Hmm, let's give it to him:
def bust_cache
MyEntities.all.each do |e|
expire_action walk_to_mordor_path(e, ??)
end
end
Problem, I can't possibly identify all choices of :direction.
Is there a way to clear all action caches that match a certain regular expression, or all action caches from a specific controller?
The secret is called expire_fragment:
expire_fragment(key, options = nil)
Removes fragments from the cache.
key can take one of three forms:
String - This would normally take the form of a path, like "pages/45/notes".
Hash - Treated as an implicit call to url_for, like {:controller => "pages", :action => "notes", :id => 45}
Regexp - Will remove any fragment that matches, so %r{pages/d*/notes} might remove all notes. Make sure you don’t use anchors in the regex (^ or $) because the actual filename matched looks like ./cache/filename/path.cache. Note: Regexp expiration is only supported on caches that can iterate over all keys (unlike memcached).
http://api.rubyonrails.org/classes/ActionController/Caching/Fragments.html#method-i-expire_fragment
Sadly, it won't work with memcached (if I ever decide to use it). Gotta be a lot more clever to avoid cache in that circunstance. Maybe adding a serial parameter to the request, and increment it when the user presses the 'bust cache' button...

Resources