How to redirect when ActionNotFound in Rails - ruby-on-rails

I have a controller SubscriptionsController with only actions new and create. How would I redirect to new if say someone tries to visit GET /subscriptions which would normally trigger the index action?
config/routes.rb
resource :subscriptions, :only => [:new, :create]

Using rails3 you can do it from a route, something like:
match "/subscriptions", :to => redirect("/subscriptions/new")
Edit:
From the comments it was made clear you want to capture more than that, using a wild card you can make it more generic. You may need to combine this form with the previous to deal with the non-slash form (or try the below form without a slash, I havent tried that). Also make sure to put these "catch all" routes below your other ones since routes are matched from top to bottom.
match "/subscriptions/*other", :to => redirect("/subscriptions/new")

Related

My Rails route is always going to show action

I have following route in my Rails project
resources :custom_urls, :path => '', :only => [:show, :new, :create]
My route is working fine for show, new and create action. But when ever I go to other paths e.g
localhost:3000/index
it always goes to show page. Due to this I am getting error because my instance variable in show action is not set. How can I avoid this problem? I want to get 404 when I try to go to other routes. I only want my application to route to show, new and create action.
Thanks in advance.
Upate
Below are my routes
Prefix Verb URI Pattern Controller#Action
root GET / custom_urls#new
custom_urls POST / custom_urls#create
new_custom_url GET /new(.:format) custom_urls#new
custom_url GET /:id(.:format) custom_urls#show
There is nothing wrong with your solution, you are just getting a little bit tricked by Rails behaviour. What is happening is, since you changed the default route path for :custom_urls to "", when you access the following url:
localhost:3000/index
The server thinks of it as
localhost:3000/custom_urls/index
So it first look for a action called "index" on your controller. Since you didn't declare it and specified that this route doesn't really exists in your route.rb, The next logical step, for rails, is to think "index" as an ID for an object of the class "Custom_url", and because of that it triggers the show action causing the error.
Basically this logic will happen for whatever you type like this:
localhost:3000/XXXX
or this, if you change the routes.rb
localhost:3000/custom_urls/XXXX
I dont recommend the following step, but if you really want to redirect the /index to 404 you would need to create the action in routes
resources :custom_urls, :path => '', :only => [:show, :new, :create, :index]
Then inside the CustumUrlsController, create the action "index" to redirect to a 404 error
def index
raise ActionController::RoutingError.new('Not Found')
end
Are you getting ActiveRecord::RecordNotFound exception? If so, it is working as expected. In dev, it shows the webconsole and in production it will display the public/404.html.
Btw, how does the user go to localhost:3000/index page? Does your app has a menu item with /index?
If you observe rake routes carefully, localhost:3000/blah (when blah is not new) is same as telling your app find me custom_url with id blah. In this case the blah is index. It could be any thing and if it is a valid id it will fetch the record. localhost:3000/new takes precedence over localhost:3000/notnew.

Rails custom route not working

Feel like I'm doing this right, but apparently not.
I have a restful resource, Posts, with index, show, new, update, edit, etc actions in the controller. In routes, I have
resources :posts
I wanted to make the index action occur at the URL '/archive' instead of '/posts'
So I added this line in the routes.rb file, after the resources one:
match '/archive', to: "posts#index"
But when I click on a link to posts_path, it still goes to /post (though if I type in /archive as a url, it works -- not ideal, though). Confused. Could this have to do with my having installed friendly_id?
resources :posts, except: [:index]
get 'archive' => 'posts#index', as: :posts
You need to use something like match '/archive', :to => 'posts#index', :as => 'archived'. Then you will have a new route to the tune of archived_posts_path. The method posts_path does not dynamically changed based on custom matchers. You can always run rake routes to see a list of routes for your site.

Removing a route

Since I used scaffolding to create my Deposit model,
resources :deposits
generates a bunch of routes. i want to be able to delete some of those routes for particular models. For example I do not want a "deposts/23/edit" route. I know I can do a redirect in the controller or do a
match "deposits/:id/edit", :to => "deposit#new"
which just shows the new deposit page but does not change the url on the browser.
is there a way to completely remove a certain action through declaring something in the rails routes.rb file. so that particular actions are just not accessible.
I reccomend looking over the Ruby on Rails Guide for Routing it discuses important core concepts and presents you with some good information on how routes are wired the way they are.
If you still wish to remove the edit route you will find a useful part of the guide here the code you need is listed below:
resources :deposits, :except => :edit
resources :deposits, :only => { :create, :new }
resources :deposits, :except => :edit

Ruby on rails Authlogic gem and Password_Reset without ending in Edit

I followed this password_reset tutorial and was able to get it working. But there are a few things I don't like about it that I want to change.
I'd like it to say password_reset rather than reset_passwords in the url. Which I've managed to accomplish by renaming the controller and routing it in config/routes.rb as map.resources :reset_passwords, :as => 'reset_password', :only => [:index, :create, :edit, :update]
I'd like to have domain.com/password_reset to link to the password_reset page, rather than having domain.com/password_reset/new
I was able to do this by changing it so that the view with the form where you enter your email is no longer "new" but "index".
I'd like to have it so when the user is emailed with the perishable_token, it gives them a url like domain.com/password_reset/perishable_token or domain.com/verify_password_reset/perishable_token rather than domain.com/password_reset/perishable_token/edit.
Or at the least I'd like to have it as domain.com/password_reset/perishable_token/verify
I cannot figure out how to get the third one to work.
I figured out how to change it to domain.com/password_reset/perishable_token rather than domain.com/password_reset/perishable_token/edit. I simply took the code from the Edit view and placed it in the Show view.

named route (RESTful) for actions other than index, delete, create, and edit

To illustrate:
class Customer
has_many :sales_orders
end
class SalesOrder
belongs_to :customer
end
i want to have customer to list sales_order which is ready to be sent, should i:
put the routing http://.../sales_orders/can_be_delivered or
create a new controller for reporting http://.../reports/sales_orders_can_be_delivered
for the 1st one, what should goes in the route.rb?
for the 2nd one, nothing goes in route.rb, we can use the last defined route which is :controller/:action.. <-- but this isn't named route
any ideas for this kind of problem?
I would go with the first option as the view you want is just another view on sales orders for which you already have a resource/controller.
The routes would be:
map.resources :sales_orders, :collection => {:can_be_delivered => :get}
This will give you .../sales_orders/can_be_delivered and the helpers can_be_delivered_sales_orders_path + can_be_delivered_sales_orders_url
Side notes
Along with the option :collection you could also add :only => [:new, :create, :destroy] if for example your controller only needed new, create and destroy from the standard restful actions.
ps. Make sure you put this above catch all route at the bottom which I would recommend you commenting out if all your actions are restful.
Finally this guide is a great start for routing in rails:
http://guides.rubyonrails.org/routing.html

Resources