Username in urls - Ruby on Rails - ruby-on-rails

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

Related

Michael Hartl Tutorial, no routes match

I get this error:
Failures:
1) UsersController DELETE 'destroy' should sign a user out
Failure/Error: delete :destroy
ActionController::UrlGenerationError:
No route matches {:controller=>"users", :action=>"destroy"}
My test is:
it "should sign a user out" do
test_sign_in(Factory(:user))
delete :destroy
expect(controller).to_not be_signed_in
expect(response).to redirect_to(root_path)
end
The test_sign_in function is in the spec helper:
def test_sign_in(user)
controller.sign_in(user)
end
My rake routes:
Prefix Verb URI Pattern Controller#Action
sessions_new GET /sessions/new(.:format) sessions#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
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
root GET / pages#home
contact GET /contact(.:format) pages#contact
about GET /about(.:format) pages#about
help GET /help(.:format) pages#help
signup GET /signup(.:format) users#new
signin GET /signin(.:format) sessions#new
signout GET /signout(.:format) sessions#destroy
pages_home GET /pages/home(.:format) pages#home
Anyone knows how can I solve this error?
Your route is defined as
DELETE /users/:id(.:format) users#destroy
which means that the route is expecting something like
DELETE /users/4
Looking at your test, you are just requesting DELETE /users, this was derived from this error message:
ActionController::UrlGenerationError: No route matches {:controller=>"users", :action=>"destroy"})
So, you need to modify your test to handle the :id part of the route. This is un-tested, but you're roughly looking for:
user = Factory(:user)
test_sign_in(user)
delete :destroy, id: user.id
ooooh god!! I found the error. I accidentally was writing the code in the users_controller_spec and I should do this in the sessions_controller_spec.
Thanks Andreas for trying to help!

Restricting Rails routes to actions

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

Making Rails routing beautiful

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

error when routing

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.

routing error on Ruby on Rails

I am doing Michael Hartl's Ruby on Rails Tutorial and I am getting a routing error.
Here is the terminal output after doing 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
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
root / static_pages#home
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
help /help(.:format) static_pages#help
about /about(.:format) static_pages#about
contact /contact(.:format) static_pages#contact
Routing error is as below
when localhost:3000/signin/ OR localhost:3000/sessions/new
No route matches {:action=>"destroy", :controller=>"sessions"}
Does anybody have an answer on how to correct the route settings?
Do you have a line like this in your routes file?
match '/signout', :to => 'sessions#destroy'

Resources