Lets say I have an UsersController that contains an action #new. In my routes file I map with the following:
match 'signup', to: 'users#new'
This action can now be accessed by both /signup and /users/new. How do I restrict it to only the custom route.
I apologize if this has been answered, but am new to this. I've searched, but haven't found the answer. Possibly due to my not knowing how to concisely phrase this.
You can exempt the new route from the users resource, and replace it with your custom route:
resources :users, except: [:new]
get 'signup', to: 'users#new', as: "new_user"
Resulting in:
users GET /users(.:format) users#index
POST /users(.:format) users#create
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
new_user GET /signup(.:format) users#new
Related
I am working on a project which includes signup, login and users can post articles. However I want to include username of the user in article url. So I did like this in routes.rb
scope '/:username' do
resources :articles, :path => '/status', only: [:create, :destroy, :show]
end
Now when I open project index which shows all articles, I am getting this error.
No route matches {:action=>"create", :controller=>"articles"} missing required keys: [:username]
Am I doing something wrong?
Edit:
Here is the output of rake routes
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root GET / static_pages#home
help GET /help(.:format) static_pages#help
signup GET /signup(.:format) users#new
login GET /login(.:format) sessions#new
POST /login(.:format) sessions#create
logout DELETE /logout(.:format) sessions#destroy
GET / users#index
POST / users#create
GET /new(.:format) users#new
GET /:id/edit(.:format) users#edit
GET /:id(.:format) users#show
PATCH /:id(.:format) users#update
PUT /:id(.:format) users#update
DELETE /:id(.:format) users#destroy
archings POST /:username/status(.:format) articles#create
arching GET /:username/status/:id(.:format) articles#show
DELETE /:username/status/:id(.:format) articles#destroy
Here is the code of routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users, shallow: true do
resources :articles
end
end
Although having really short URLs may be attractive you should not use a wildcard at the "lowest level" of your url schema - unless your application only really deals with a single type of resource. Adding a wildcard at the bottom level in your urls causes huge headaches since it will swallow every other route unless great care is taken.
I would really recommend that you use /users/:username/articles.
resources :users, shallow: true do
resources :articles
end
This is a better restful design and it means that you do not have to blacklist usernames against a list of the other urls (and future urls) needed in your application.
Added:
The output of $ rake routes:
Prefix Verb URI Pattern Controller#Action
user_articles GET /users/:user_id/articles(.:format) articles#index
POST /users/:user_id/articles(.:format) articles#create
new_user_article GET /users/:user_id/articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Suppose you have UsersController and routes are configured in config/routes.rb as the followings.
root 'users#index' # root should list all users
resources :users
Then rake routes shows
Prefix Verb URI Pattern Controller#Action
root GET / users#index
users GET /users(.:format) users#index
users POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
There are a couple of URIs indicating same users#index action.
Should I prevent this kind of URI duplication or should I let them alone for me to follow Rails' default convention?
There are a couple of URIs indicating same users#index action. There are a couple of URIs indicating same users#index action.
Well, that's what you've specified by creating the users resource and then pointing the root path to users#index. If you don't want this behavior, you can remove the default index action from the resource.
resources :users, except: [:index]
Note that with this place, you can no longer refer to the index path via the traditional URL helpers. Personally I wouldn't be concerned with this and just let the URL duplication exist.
For root it's okay--this is typical and it's just redirecting to the users resource.
I have the following in my Rails routes.rb:
resource :sign_up, only: [:new, :create]
resources :users
get 'users/activate/:token' => 'users#activate', as: 'activate_user'
Which gives me the following routes:
Prefix Verb URI Pattern Controller#Action
sign_up POST /sign_up(.:format) sign_ups#create
new_sign_up GET /sign_up/new(.:format) sign_ups#new
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
activate_user GET /users/activate/:token(.:format) users#activate
I'd like to get rid of the get 'users/activate/:token' ... route and use nesting or scoping instead, though I can't figure it out. Is there a way to accomplish this?
Thanks!
You can set up a collection route for users:
resources :users do
collection do
get 'activate/:token', :action => :activate, :as => :activate
end
end
And it will give you routes like this:
Prefix Verb URI Pattern Controller#Action
activate_users GET /users/activate/:token(.:format) users#activate
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
In my rails app following in routes.rb
resources :users
leads to following output for 'rake routes'
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
& following in routes.rb (for my custom controller 'home')
match '/new_user' => 'home#new_user', via: [:get]
match '/users/:id/edit' => 'home#edit_user', via: [:get]
match '/users/:id' => 'home#show_user', via: [:get]
match '/users/:id' => 'home#create_user', via: [:post]
leads to following output for 'rake routes'
GET /new_user(.:format) home#new_user
GET /users/:id/edit(.:format) home#edit_user
GET /users/:id(.:format) home#show_user
POST /users/:id(.:format) home#create_user
why there are no path names for second case? like in first case ('new_user', 'edit_user')
is there any way to have path names for second case? as i want to use these path names in my views
There are no path names because you haven't specified path names. If you're supplying custom routes instead of using resources, you need to use :as to provide a pathname:
match '/new_user' => 'home#new_user', via: :get, as: :new_user
You should also just use get instead of match... via: :get:
get '/new_user' => 'home#new_user', as: :new_user
However, given your set of routes, your better bet is to continue using resources, but to supply a limited list of actions via :only and a custom controller via :controller:
resources :users, only: %w(new edit show create), controller: "home"
I have routes defined to some static pages and also to some controllers (users and usymptoms).
When I navigate to localhost:3000/users/1 or localhost:3000/users/1/usymptoms/new everything is fine. Once I finish filling in the form on symptoms/new, I have the usymptoms controller redirecting to #users. This works fine.
In the model file, the association is users has many usymptoms and usymptoms belongs to user.
However, now my static pages are not accessible. For example, when I navigate to /learn, I get the following error:
No route matches {:action=>"new", :controller=>"usymptoms", :user_id=>nil}
I am new to rails. Can you please help me figure out the error?
I have provided my routes file and the output from "rake routes" below.
My routes.rb file
root to: 'static_pages#home'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
match '/learn', to: 'static_pages#learn'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
resources :users do
resources :usymptoms
end
resources :sessions, only: [:new, :create, :destroy]
======
Output from rake routes
root / static_pages#home
about /about(.:format) static_pages#about
contact /contact(.:format) static_pages#contact
learn /learn(.:format) static_pages#learn
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
user_usymptoms GET /users/:user_id/usymptoms(.:format) usymptoms#index
POST /users/:user_id/usymptoms(.:format) usymptoms#create
new_user_usymptom GET /users/:user_id/usymptoms/new(.:format) usymptoms#new
edit_user_usymptom GET /users/:user_id/usymptoms/:id/edit(.:format) usymptoms#edit
user_usymptom GET /users/:user_id/usymptoms/:id(.:format) usymptoms#show
PUT /users/:user_id/usymptoms/:id(.:format) usymptoms#update
DELETE /users/:user_id/usymptoms/:id(.:format) usymptoms#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
You must have the following link somewhere: new_user_usymptom_path(#user), but #user is nil for some reason, hence the error.