Reduce complexity of routes - ruby-on-rails

I am attempting to setup my routes.rb so that /sessions/ is not required in the url for logging in and out of the site. Below are my samples to show what I am trying to achieve. Whilst the "second attempt" does in fact do what I want, I'd like to know if there is a more efficient way of doing this. I am very new to rails and I am sure that the routes.rb has some option that can do what I am doing in three large lines.
First attempt
routes.rb
namespace :account do
resources :users
resources :sessions
end
$ rake routes
Prefix Verb URI Pattern Controller#Action
account_users GET /account/users(.:format) account/users#index
...
account_sessions GET /account/sessions(.:format) account/sessions#index
POST /account/sessions(.:format) account/sessions#create
new_account_session GET /account/sessions/new(.:format) account/sessions#new
edit_account_session GET /account/sessions/:id/edit(.:format) account/sessions#edit
account_session GET /account/sessions/:id(.:format) account/sessions#show
PATCH /account/sessions/:id(.:format) account/sessions#update
PUT /account/sessions/:id(.:format) account/sessions#update
DELETE /account/sessions/:id(.:format) account/sessions#destroy
Second attempt
routes.rb
namespace :account do
resources :users
match '/login', :controller => 'sessions', :action => 'new', :via => [:get]
match '/login', :controller => 'sessions', :action => 'create', :via => [:post]
match '/logout', :controller => 'sessions', :action => 'destroy', :via => [:delete]
end
$ rake routes
Prefix Verb URI Pattern Controller#Action
account_users GET /account/users(.:format) account/users#index
...
account_login GET /account/login(.:format) account/sessions#new
POST /account/login(.:format) account/sessions#create
account_logout DELETE /account/logout(.:format) account/sessions#destroy
Can this be done without having to manually specific the match locations? All I want to do is remove /sessions/ as a requirement.

namespace :account do
resources :users #-> account/users
resources :sessions, path: "", path_names: { new: "login", create: "login", destroy: "logout" } #-> accounts/login, accounts/logout
end

I hope you realise you have /login twice in your second example. This simplifies it a bit but you will always have to match each route you want to specify outside any defaults.
namespace :account do
match '/login', to: 'sessions#new', via: [:get]
match '/logout', to: 'sessions#destroy', via: [:delete]
end

In rails3 we should use with_options in following way:
scope '/account' do
match '/login' => "sessions#new", :as => :login
post '/:login' => 'sessions#create', :as => :signup_create
delete '/:logout' => 'sessions#destroy', :as => :logout
end

Related

How to remove ControllerName from a Rails Resource?

I wish to map new_user path of the user resource to 'ROOT_DOMAIN/new' URL. My routes.rb looks something like this:
#new_user GET /users/new(.:format) users#new
# User Resource
match 'new', :to => 'users#new', via: [:get, :post]
resources :users do
collection do
match 'new', :to => 'users#new', via: [:get, :post]
end
end
So while I'm able to hit the /new URL to the desired action with
match 'new', :to => 'users#new', via: [:get, :post]
but the new_user path still leads to '/users/new'. How to remove the controller_name from the new_user method?
Your new_user_path takes you to user#new because that's how rails build resourceful routes. Have a look at rails guides to learn more. You need to pass the as: option to your routes in order to give them proper helper methods like:
post '/home' => "home#index", as: :home
This will give you two helpers home_path and home_url
Now you have
resources :users do
collection do
match 'new', :to => 'users#new', via: [:get, :post]
end
end
If you do rake routes in your terminal you'll see that new_user helpers are assigned to user#new. You need to give it a different path helper and then assign your new_user helpers to your custom route
resources :users do
collection do
match 'new', :to => 'users#new', via: [:get, :post], as: :old_new_user
end
end
and then you can use your new_user helper for your custom route
match 'new', :to => 'users#new', via: [:get, :post], as: :new_user
You can check your path helper by doing rake routes in terminal

Static routes no longer working, passing id

I had routes like this
/state/arizona/unit/AZ22
I wanted to remove the controller names of STATE and UNIT and get routes like this
/arizona/AZ22
Found this code which worked great
resources :states, :except => [:index ], :path => '/' do
resources :units, :except => [:index ], :path => '/'
end
But now my static paths don't work because it thinks it is a state. I have a list of States on the static pages.
Error: Couldn't find State with id=about
Code throwing error : def set_state
#state = State.friendly.find(params[:id])
end
These are my static page routes
match '/contact', to: 'static_pages#contact', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
root 'static_pages#home'
Is there a way to fix the routes?
Or did I use static pages wrong because I'm feeding a list of states to them?
Routes are matched in the order they are specified. So, organize your routes as follows and give it a try:
root 'static_pages#home'
match '/contact', to: 'static_pages#contact', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
resources :states, :except => [:index ], :path => '/' do
resources :units, :except => [:index ], :path => '/'
end

Rails: Define routes manually after modifying to_param

I have been trying to implement a vanity url for user profiles, based on the example here: Rails 3: Permalink public profile. I have replaced the 'id' with username:
def to_param
username
end
However this has caused issues with my other routes. I have set them so that they match the default sets of routes exactly, when running 'rake routes'.
get '/users/' => 'users#index', :as => :users
post '/users' => 'users#create'
get '/users/new' => 'users#new', :as => :new_user
get '/users/:id/edit' => 'users#edit', :as => :edit_user
patch '/users/:id' => 'users#update'
put '/users/:id' => 'users#update'
delete '/users/:id' => 'users#destroy'
# for vanity url
get '/:id' => 'users#show', :as => :user
With this setup, trying to access delete and update routes give me 'no route matches' error. What is the proper way to specify these, and / or should I be doing this a different way? Any help is appreciated.
I think it's interresting and more readable to keep the resources syntax in the routes.rb, except for the show, which you can rewrite to customize user_path :
resources :users, :except => [:show]
# 2 possibilities for the show url
get '/users/:id' => 'users#show' # can be removed if you don't want to keep /users/:id url
get '/:id' => 'users#show', :as => :user
But change the controller to find user by username instead of id, for example
def show
#post = Post.find_by_username(params[:id]) # instead of Post.find(params[:id])
# ...
end

Reusing the name of a custom RESTful route in Rails 3

I want to do something that I imagine looks like this:
resources :users do
collection do
get 'login', :action => 'login_form'
post 'login', :action => 'login'
get 'logout'
end
end
I.e. I want two controller actions to bind to the same path with different methods. How do I do that?
You should read the guide about routes: http://guides.rubyonrails.org/routing.html
resources :users do
collection do
match 'login' => "users#login_form", via: :get
post 'login'
get 'logout'
end
end
A login_form action does not sound very restful. Just saying ;)

Not getting a [:id] parameter from url, Default route is not working

When I request a URL as follows:
http://localhost:3000/password_resets/edit/4RghIKJNygEDswIuuCo
I'm not getting the [:id] parameter, i.e. 4RghIKJNygEDswIuuCo.
Here is my route file, are there any modifications required for this?
ActionController::Routing::Routes.draw do |map|
match 'primary', :to => 'pages#primary', :as => "primary"
match 'admins', :to => 'admin_users#list', :as => "admins"
match 'login', :to => 'user_sessions#new', :as => "login"
match 'logout', :to => 'user_sessions#destroy', :as => "logout"
root :to =>"public#index"
match 'HFA/:id/' => 'public#show'
match 'HFA/:id/:uid' =>'public#show'
match 'public/projectview/:projectid/' => 'public#projectview'
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:action/:id'
resources :users
resources :usertypes
resources :user_sessions
end
The default is /controller/:id/edit, following the REST architecture.
Do you really want to change this?
If so, verify the order of the declarations:
Rails routes are matched in the order they are specified, so if you
have a resources :photos above a get 'photos/poll' the show action’s
route for the resources line will be matched before the get line. To
fix this, move the get line above the resources line so that it is
matched first.
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
and check your availables routes with the rake routes command:
http://guides.rubyonrails.org/routing.html#inspecting-and-testing-routes
if you put match instead of 'get' you will get all http (GET, POST, PUT, DELETE) route verbs
get 'password_resets/:id/edit', to: 'password_reset#create', as: :send_password_reset
the 'to:' defines the controller method, 'as:' defines the path name, 'get' defines the route verb and ':id' is the token created by this line in app/views/user_mailer/password_reset.text.erb
<%= send_password_reset_url(#user.password_reset_token) %>
run "rake routes" command and check the routes for "password_resets/edit/4RghIKJNygEDswIuuCo".

Resources