Rails Routing Error? 'No route matches' - ruby-on-rails

So I keep running into the following error:
No route matches {:action=>"show", :controller=>"users"}
I tried running rake routes and I can see that the route exists:
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
But every time I try visiting the page "/users/1" (1 being the user id), I get the above error. Any ideas? Thanks!
Here's my routes.rb:
SampleApp::Application.routes.draw do
root to: 'static_pages#home'
resources :users
resource :sessions, only: [:new, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
Here's my users_controller.rb:
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
before_filter :correct_user, only: [:edit, :update]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Paper Piazza!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
def index
#users = User.paginate(page: params[:page])
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_path, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
end

Try fixing the typo:
root :to 'static_pages#home'
(rather than root to:), and moving it to the last line of the block. And let me know if that makes a difference!
What's odd is that I built a fresh project with a routing file that simply reads:
RoutingTest::Application.routes.draw do
resources :users
root :to => "static_pages#home"
end
When I ran this in the console, I got the same error you're seeing:
>> r = Rails.application.routes ; true
=> true
>> r.recognize_path("/users/1")
=> ActionController::RoutingError: No route matches "/users"
... but when I run the same thing in a slightly older project, I get:
>> r = Rails.application.routes ; true
=> true
>> r.recognize_path("/users/1")
=> {:action=>"show", :controller=>"users", :id=>"1"}
So I have little confidence that what I'm telling you will make a difference. (Aside from that, the Rails.application.routes trick is useful for verifying paths in the console!)

I had a similar problem, I had routes that would just return the root page, but would show up in rake routes. According to a fellow developer for a specific namespace and for all routes the root to: (routing) must always be last. This is in contradiction to the Rails guide on routing (see http://guides.rubyonrails.org/routing.html#using-root) which says that any call to root should be at the top of your file. That was definitely not working for me. Interesting...

Related

Route does not match in test but is recognized in application

I am following Michael Hartl's tutorial, chapter 10. Test UsersControllerTest#test_should_redirect_edit_when_logged_in_as_wrong_user fails when trying to do get edit_user_path(#user).
get edit_user_path(#user)
ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111/edit", :controller=>"users"}
from /Users/cello/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/actionpack-5.1.4/lib/action_dispatch/journey/formatter.rb:55:in `generate'
However:
Rails.application.routes.recognize_path '/users/762146111/edit', method: :get
=> {:controller=>"users", :action=>"edit", :id=>"762146111"}
Below is the code that might have a bug (Rails 5.1.4).
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post 'signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get 'sessions/new'
resources :users
end
users_controller_test.rb
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test 'should redirect edit when logged in as wrong user' do
log_in_as(#other_user)
get edit_user_path(#user)
assert flash.empty?
assert_redirected_to root_url
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def edit
#user = User.find(params[:id])
end
private
def logged_in_user
unless logged_in?
flash[:danger] = 'Please log in.'
redirect_to login_url
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
end
The tutorial is defining an Integration Test (inherits from ActionDispatch::IntegrationTest), whereas your above code is defining a Controller Test (inherits from ActionController::TestCase).
get :edit, ... is the correct syntax for a controller test, because it bypasses URL recognition and directly specifies the :action. This is confusing, and is one of several reasons that controller tests are now discouraged in favour of integration tests, which is probably what you want to create.
To do so, change:
class UsersControllerTest < ActionController::TestCase
to:
class UsersControllerTest < ActionDispatch::IntegrationTest
(Note the tutorial, somewhat confusingly, uses ActionDispatch::IntegrationTest as the base class both for tests it puts in tests/integration/ and those it puts in tests/controllers/.)
You can not use direct url with 'get' method in spec.
In your spec instead of
get edit_user_path(#user)
use
get :edit, params: { id: #user.id }
the same with
patch user_path(#user)
use patch :update instead

Admin function in rails: Error: Couldn't find User with 'id'=

I am trying to write an update function, which allows to pick a user in a list of users and update that user to make it an admin. The important function in the controller should be def change_admin.
Thanks for your help!
I tried several options, but I run into that error:
Couldn't find User with 'id'=
My Controller:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def new
#user = User.new
end
def index
#users = User.where(activated: true).paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
redirect_to root_url and return unless #user.activated
end
def edit
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Der Nutzer wurde gelöscht"
redirect_to users_url
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to root_path
else
render 'edit'
end
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Bitte öffnen Sie Ihr E-Mail Postfach, um den Account zu aktivieren."
redirect_to root_url
else
render 'new'
end
end
def admin
#users = User.where(activated: true).paginate(page: params[:page])
end
def change_admin
#user = User.find(params[:id])
#user.update_attribute(:admin,true)
respond_to do |format|
format.html { redirect_to admin_path }
end
end
# Before filters
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation,
:mat_number, :ects, :grade_avg, :enrolled, :matched_institute)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
I also tried to delete the user.find line, but that gives me another error:
undefined method `update_attribute' for nil:NilClass
My routes file:
Rails.application.routes.draw do
resources :preferences
resources :institutes
get 'password_resets/new'
get 'password_resets/edit'
get '/users_show', to: 'users#show'
get '/users/new'
root 'static_pages#home'
get '/home', to: 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/matching', to: 'static_pages#matching'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/admin', to: 'users#admin'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
get '/performance_show', to: 'users#performance_show'
get '/performance_update', to: 'users#performance_update'
post 'preferences/create_all', :to => 'preferences#create_all'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
post 'preferences/delete_matching', :to => 'preferences#delete_matching'
post 'preferences/read_and_show_ofv', :to => 'preferences#read_and_show_ofv'
post 'preferences/read_matching', :to => 'preferences#read_matching'
post 'preferences/optimize_matching', :to => 'preferences#optimize_matching'
post 'preferences/optimize', to: 'preferences#optimize'
end
Your routes are in pretty bad shape. You have tons of duplication as well as routes that are missing the :id segment to make them work:
get '/users_show', to: 'users#show'
get '/users/new'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
resources :users already declares a proper show route as GET /users/:id and new as /users/new.
To add additional RESTful routes you should instead pass a block to resources:
resources :users do
# this should be PATCH not POST
patch :change_admin
end
This will create the proper route as /users/:id/change_admin.
You are also using the wrong HTTP verb in many places like for example get '/performance_update', to: 'users#performance_update'. Never use GET for actions that create or alter a resource as the call ends up in the browsers history and may be cached.
Adding update, change, create in the path of your route should be a big red flag that you´re doing it wrong.
I would recommend that you read the guides thoroughly before adding more cruft.

How to create an admin user with Ruby on Rails

I'm new to ruby on rails, and so far, I have created the user login, signup, signout, but I wanna create an admin user, and I have no idea how to do this.
route.rb is:
Rails.application.routes.draw do
get 'courses/index'
get 'courses/new'
get 'courses/edit'
get 'courses/show'
get 'course/index'
get 'course/new'
get 'course/edit'
get 'course/show'
get 'sessions/signin'
get 'sessions/main'
get 'sessions/profile'
get 'sessions/setting'
get 'users/new'
get 'home/index'
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout"} do
collection do
get :signin
get :main
get :profile
get :setting
end
end
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
#resources :course, only: [:index, :new, :edit, :show]
resources :courses
resources :course_groups
patch 'course_groups/:id/add_course', to: 'course_groups#add_course', as: 'course_group_add_course'
delete 'course_groups/:id/delete_course', to: 'course_groups#destory_course', as: 'course_group_destory_course'
resources :rules
patch 'rules/:id/add_group', to: 'rules#add_group', as: 'rule_add_course_group'
delete 'rules/:id/delete_group', to: 'rules#destroy_group', as: 'rule_destroy_course_group'
resources :requirements
patch 'requirements/:id/add_rule', to: 'requirements#add_rule', as: 'requirement_add_rules'
delete 'requirements/:id/delete_rule', to: 'requirements#destroy_rule', as: 'requirement_destroy_rules'
#resources :plans
resources :users do
resources :plans
end
patch 'users/:user_id/plans/:id/add_course', to: 'plans#add_course', as: 'plan_add_course'
delete 'users/:user_id/plans/:id/delete_course', to: 'plans#destory_course', as: 'plan_destory_course'
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
#match '/profile', to: 'sessions#profile', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
match '/show', to: 'users#show', via: 'get'
match '/profile', to: 'users#profile', via: 'get'
#match '/info', to: 'users#info', via: 'get'
#match '/changepass', to: 'users#edit', via: 'get'
end
and my users_controller.rb is:
class UsersController < ApplicationController
before_filter :check_if_signned_in, only: [:show, :edit, :update, :delete]
before_filter :signed_in_user, only: [:edit, :update]
before_filter :skip_password_attribute, only: :update
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user, notice: 'User was sucessfully created!'
else
render action: "new"
end
end
#if current user exits, then it can get back to the main page of user
def show
if current_user.nil?
#user = User.find(params[:id])
else
#user = User.find(current_user)
end
end
def edit
##user = User.find(params[:id])
##user = User.find(current_user)
#user = current_user
#user.save
#title = "Edit profile"
end
def update
#user = User.find(params[:id])
##user = User.find(current_user)
#if #user.update_attributes(user_params)
if #user.update_attributes(user_params)
flash[:success] = "Profile updated."
#sign_in #user_params
redirect_to #user
else
#title = "Edit profile"
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def signed_in_user
redirect_to signin_path, notice: "Please sign in." unless signed_in?
end
def edit_user
params.require(:user).permit(:name)
end
def skip_password_attribute
if params[:password].blank? && params[:password_confirmation].blank?
params.except!(:password, :password_confirmation)
end
end
end
the application_controller.rb is:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
#protect_from_forgery with: :exception
protect_from_forgery
#before_filter :session_expire
#before_filter :update_active_time
include SessionsHelper
def check_if_signned_in
deny_access unless signed_in?
end
#def update_active_time
# session[:expires_at] = default_expire
#end
def is_owner
current_user.id == params[:id]
end
#private
# def get_session_time_left
# expire_time = session[:expires_at] #|| default_expire
# a = expire_time
# b = Time.now
# #session_time_left = (a - b).do_i
##session_time_left = (expire_time - Time.now).do_i
# end
end
Anyone can teach me how to create an admin user please? When the admin user logins, it will go to another different page.
Thank you in advance!
Without being rude, your code really needs to be cleaned up.
Your routes alone are a mess - I think I remember giving you some code to help them the other day, and it appears you've used it! However, you've left the other routes in there still - which is likely going to cause big issues down the line
Routes
Firstly, you need to get your routes in order:
#config/routes.rb
resources :courses
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout", index: "main", edit: "profile", update: "setting"}
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
resources :course_groups do
patch :add_course
delete :delete_course
end
resources :rules do
patch :add_group
delete :delete_group
end
resources :requirements do
patch :add_rule
delete :delete_rule
end
resources :users do
resources :plans do
patch :add_course
delete :delete_course
end
end
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
Simply, everything in Rails is resource / object - orientated. This includes the routes, and you should therefore make sure that every route you have is constructed around a resource (that's why you can define routes as resources etc)
--
Admin
To create an admin user, there are several options available to you:
Have a separate admin model
Create an admin attribute in your User model
I would strongly recommend including an admin attribute in your User model - make it a boolean column like this:
#new migration
add_column :users, :admin, :boolean
This will allow you to call the following
#user = User.find params[:id]
#user.admin? #-> true / false
This will allow you to use several conditional statements in both the controllers & views of your application, to determine if the user had admin privileges or not

Routing Error Try running rake routes

I got 2 diferents message but whit the same error, Im using a devise for users... Here is my routes.rb
Estaciones::Application.routes.draw do
root :to => "static_pages#home"
match '/contact', :to=>'static_pages#contact'
match '/about', :to=>'static_pages#about'
devise_for :users
resources :users
whit my routes.rb just like that i got the next error
uninitialized constant UsersController
Try running rake routes for more information on available routes.
but if a remove the "resourses: users" i got the following error
No route matches [GET] "/users/27"
I put my UsersController
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to user_session_path
else
redirect_to new_user_session_path
end
end
def show
#user = User.find(params[:id])
#redirect_to #user
end
end
The filename for your users model must be users_controller.rb and be in the controllers folder.

No route matches [GET] "/microposts/x" Chapter 10, Hartl's Ruby on Rails tutorial should be delete link

I cannot figure out why I am getting this error. I know this question is very similar to this question, but I have all the jquery links correct as verified by the fact that I can delete users without a problem but not the microposts. When I try the example in the browser and click the delete link(http://localhost:3000/microposts/253) on a micropost, even though the item does get deleted the browser says:
Routing Error
No route matches [GET] "/microposts/253"
Try running rake routes for more information on available routes.
Test result:
Micropost pages micropost destruction as correct user should delete a micropost
Failure/Error: expect { click_link "delete" }.should change(Micropost, :count).by(-1)
ActionController::RoutingError:
No route matches [GET] "/microposts/1"
routes.rb
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :microposts, only: [:create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
root to: 'static_pages#home'...
Microposts delete link:
<%= link_to "delete", micropost, method: :delete,
confirm: "You sure?",
title: micropost.content %>
Microposts controller:
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_path
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
redirect_back_or root_path
end
private
def correct_user
#micropost = current_user.microposts.find_by_id(params[:id])
redirect_to root_path if #micropost.nil?
end
end
I am unable to find the 3.2 tutorial repo to compare my sample_app to but I think I've followed the tutorial to the letter. Any help is appreciated.
Yes, The problem is that you haven't updated your routes. Inside your routes.rb file, you have resources :microposts, only: [:create, :destroy]. The route that its looking for is a :show to :microposts.
Without seeing your controller code, I suspect that after you delete the micropost, you are trying to redirect back to the micropost. Either update your route to this: resources :microposts, only: [:create, :destroy, :show] or post up the details of your microposts controller.
I had the same problem, and after restarting the rails server it worked fine for me.
[posting if anyone visits this page lately]
As I can see the problem is that your delete request goes as 'GET', But as per the REST conversions it should be a 'POST' request,
And I just created a sample app with Rails 3.1.3 and its delete link is as follows
In this case I have created a scaffold called User
<%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %>
You can check what is happening to your delete request by using Firebug with Firefox
I am working through the same tutorial, and am having the same problem. My analysis is that the problem is because we are using redirect_back_or root_path in the microposts controller (~/rails_projects/sample_app/app/controllers/microposts_controller.rb):
class MicropostsController < ApplicationController
...
before_filter :correct_user, only: :destroy
...
def destroy
#micropost.destroy
logger.debug "in MicropostsController.destroy:"
logger.debug " root_path=#{root_path}"
logger.debug " session[:return_to]=#{session[:return_to]}"
redirect_back_or root_path
end
The output from the logger.debug statements shown is:
in MicropostsController.destroy:
root_path=/
session[:return_to]=/microposts/28
Recall that redirect_back_or is defined in sessions_helper.rb as:
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
So, the call to redirect_back_or root_path will result in:
redirect_to(/microposts/28)
I'm a newbie here, but I think the default action is GET; at least, that's consistent with what I'm seeing, i.e. this is why we are posting a GET to /microposts/28.
Meanwhile, in routes.rb, we have defined the resource microposts to only support create and destroy actions:
resources :microposts, only: [:create, :destroy]
Of course, we don't want to GET the micropost we just deleted; we want to re-render (or re-direct?) back to the page from which we came. As evidence that this analysis is correct as far as it goes, I found that calling redirect_to root_path instead of redirect_back_or root_path "works", in that the micropost gets deleted (after popup confirmation), and puts the user back on the home page (showing the deleted micropost is gone).
I have now changed my as follows, so that the page from which the delete action was invoked re-appears:
def destroy
#micropost.destroy
redirect_to request.referer
end
I also changed my definition of SessionsHelper#store_location:
def store_location
session[:return_to] = request.fullpath if ['show', 'edit'].include?action_name
end
So, only 'show' and 'edit' actions attempt to resume after login.

Resources