Hi I am new to rails and I have just started making a facebook clone and I am starting out with the friends function, however I am getting the error ActiveRecord::RecordNotFound in UsersController#show Couldn't find User without an ID any help would be much appreciated
here is a picture of the error
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :set_user
def show
end
def friend
current_user.sent_follow_request_to(#user)
redirect_to root_path
end
def unfriend
current_user.unfollow(#user)
#user.unfollow(current_user)
redirect_to root_path
end
def accept
current_user.accept_follow_request_of(#user)
current_user.send_follow_request_to(#user)
#user.accept_follow_request_of(current_user)
redirect_to root_path
end
def decline
current_user.decline_follow_request_of(#user)
redirect_to root_path
end
def cancel
current_user.remove_follow_request_for(#user)
redirect_to root_path
end
private
def set_user
#user = User.find(params[:id])
end
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
followability
def unfollow(user)
followerable_relationships.where(followable_id: user.id).destroy_all
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
post 'users/:id/unfriend', to: 'users#unfriend', as: 'unfriend'
post 'users/:id/friend', to: 'users#friend', as: 'follow'
post 'users/:id/accept', to: 'users#accept', as: 'accept'
post 'users/:id/decline', to: 'users#decline', as: 'decline'
post 'users/:id/cancel', to: 'users#cancel', as: 'cancel'
get 'users/:id', to: 'users#show', as: 'users'
resources :users
root 'users#show'
# Define your application routes per the DSL in
https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
end
The problem is your root route:
root 'users#show'
You've defined your root web page, that is what will show up when the user requests /, as when they go to http://localhost:3000. It's set to the page which shows a specific user. This requires a User ID to do its job. But there is no ID provided.
Pick something else for your root page. users#index for example. Or your registration and sign on page. See the Devise docs for setting that up.
Related
I'm creating an app where I need only admins to create new users:
routes.rb:
devise_for :users, :skip => [:registrations]
resources :users
root 'dashboard#index'
users_controller.rb
# GET /users/1/edit
#def edit
#
#end
# POST /users
# POST /users.json
def create
build_resource(sign_up_params)
respond_to do |format|
if resource.save
format.html { redirect_to user_path(resource), notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: user }
else
clean_up_passwords resource
respond_with resource
end
end
end
When I open http://localhost:3000/users/new
I got this error:
AbstractController::ActionNotFound at /users/new
Could not find devise mapping for path "/users/new".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
What is wrong there? Thank you a lot!
The problem is that you're confusing Devise functionality with that of your app:
#config/routes.rb
resources :users #-> nothing to do with devise
When you create a user, you're using the devise build_resource helper. Problem being that this will require devise functionality, which is not going to happen for users_controller.
To use sign_up_params or build_resource, you'll have to scope your routes to a devise controller (so all the available session data is there)...
#config/routes.rb
devise_for :user, skip: [:registrations]
devise_scope :user do
resources :users, path: "", only: [:new, :create], controller: "registrations" #-> url.com/users/new
end
This way, you'll be able to override the standard Devise::RegistrationsController with your own code:
#app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :authenticate_user!
before_action :check_admin
def create
build_resource(sign_up_params)
...
end
private
def check_admin
redirect_to root_path unless current_user.admin?
end
end
--
What I would recommend is either removing the Devise functionality from your users controller, or overriding the registrations controller so that only an admin can create a user (which it seems you're trying to do already).
My rails app has 5 user models that extend User. All of which have the namespace User::UserTypeHere. When I attempt to logout of my application, devise tries to access the models as if they belong to the top level namespace, and I get the following error:
"The single-table inheritance mechanism failed to locate the subclass: 'SuperUser'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance..."
How do I set up my routes in a way that devise will recognize my namespaced models?
routes.rb snippet
...
devise_for :users, skip: [:sessions, :passwords, :confirmations, :registrations, :unlocks]
devise_scope :user do
# authentication
unauthenticated :user do
root to: 'users/devise/sessions#new', as: 'new_user_session'
end
authenticated :user do
root to: 'application#index'
end
get '/login', to: 'users/devise/sessions#new', as: 'user_login_view'
post '/login', to: 'users/devise/sessions#create', as: 'user_session'
get '/logout', to: 'users/devise/sessions#destroy', as: 'destroy_user_session'
# registrations
get '/join', to: 'users/registrations#new', as: 'new_user_registration'
post '/join', to: 'users/registrations#create', as: 'user_registration'
# user accounts
scope '/account' do
# confirmation
get '/verification', to: 'users/confirmations#verification_sent', as: 'user_verification_sent'
get '/confirm', to: 'users/confirmations#show', as: 'user_confirmation'
get '/confirm/resend', to: 'users/confirmations#new', as: 'new_user_confirmation'
post '/confirm', to: 'users/confirmations#create'
# passwords
get '/reset-password', to: 'users/passwords#new', as: 'new_user_password'
get '/reset-password/change', to: 'users/passwords#edit', as: 'edit_user_password'
put '/reset-password', to: 'users/passwords#update', as: 'user_password'
post '/reset-password', to: 'users/passwords#create'
# unlocks
post '/unlock', to: 'users/unlocks#create', as: 'user_unlock'
get '/unlock/new', to: 'users/unlocks#new', as: 'new_user_unlock'
get '/unlock', to: 'users/unlocks#show'
# settings & cancellation
# get '/cancel', to: 'users/registrations#cancel', as: 'cancel_user_registration'
# get '/settings', to: 'users/registrations#edit', as: 'edit_user_registration'
# put '/settings', to: 'users/registrations#update'
# account deletion
# delete '', to: 'users/registrations#destroy'
end
end
...
user.rb (model)
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
users/super_user.rb (model)
class Users::SuperUser < User
...
end
users/devise/sessions_controller.rb
class Users::Devise::SessionsController < Devise::SessionsController
...
end
The value of the type column for your users needs to be Users::SuperUser, instead of just SuperUser, so that Rails autoload can find the correct class path.
Also, remember to restart your rails console & server when changing classes around, and don't keep old user instances with wrong values for type, as that will force rails to trigger an error when finding them
How do I direct a user to a specific page after they have successfully signed in with devise?
I have installed devise and as they stipulate I have added root to: 'home#index'which I assume roots to the page where sign-in is rendered. What I can't figure out, is how I redirect a user to an already existing specific page like 'graph/data' once they are signed in.
If you want to redirect the user only once then you can overwrite the after_sign_in_path method wich is described in the devise documentation
ref:
## application_controller.rb
def after_sign_in_path_for(resource)
sign_in_url = new_user_session_url
if request.referer == sign_in_url
super
else
stored_location_for(resource) || request.referer || root_path
end
end
If you want that the user will redirect to a specific route if the user is sign_in you can use devise_scope:
ref:
## routes.rb
devise_for :users
devise_scope :user do
authenticated :user do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
In addition to the the bulleric's answer:
At second case:
## routes.rb
devise_for :users
devise_scope :user do
authenticated :user do
root 'graphs#data', as: :authenticated_root
end
unauthenticated do
root 'home#index', as: :unauthenticated_root
end
end
But for this case You could have 'GraphsController' with action 'data'.
Additionaly, You should use ':authenticate_user!' into this. For example:
class GraphsController < ApplicationController
before_filter :authenticate_user!
I have model User. And models
CaBase < User
LaUser < User
Both models has:
devise :database_authenticatable, :recoverable, :rememberable,
:trackable, :validatable
LaUser- Users that have access to Admin area.
CaBase - Users that has access only for front-end.
When I click on forgot password on CaBase login form, it mails me with link like:
site_name/admin/password/edit?reset_password_token=gtwSWQK8HH2-6p4CHp
But I need it to
site_name/password/edit?reset_password_token=gtwSWQK8HH2-6p4CHp
Also I have actions in ApplicationController
def after_sign_in_path_for(resource)
if resource.is_a?(LaUser)
admin_root_path
else
dashboard_index_path
end
end
def after_sending_reset_password_instructions_path_for(resource)
if resource.is_a?(LaUser)
admin_root_path
else
dashboard_index_path
end
end
What can I do with it?
UPD1:
get 'dashboard/index'
ActiveAdmin.routes(self)
devise_for :la_users, ActiveAdmin::Devise.config
devise_for :ca_base, path: '', path_names: {sign_in: 'login'}
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'welcome#index'
resource :ca_administrators, only: [:new, :create]
Problem was in that I don't checked which role have current user.
Code from Devise Mailer.
if record.is_a?(LaUser)
controller = 'active_admin/devise/passwords'
else
controller = 'devise/passwords'
end
edit_password_url = url_for(
controller: controller,
action: :edit,
reset_password_token: token
)
I am new in Ruby On Rails. I am making an application using devise gem. My requirement is after logged in successfully I should redirect to devise controller again.
I have created devise controller as 'Users'
I have created one more controller home_controller.rb for redirecting
under home controller I have coded this.
def index
if user_signed_in?
redirect_to :controller => 'users', :action =>add
end
end
I have written add method under users_controller.rb
And under routes.rb I have coded this
devise_for :users, controllers:{sessions: "users/sessions"}
root :to => 'home#index'
match 'users/:action' => 'users#add', :as => :add
But its not redirecting. What should I do. any help. Thanks
Try this:-
resources :users do
member do
get "add"
end
end
If I understand correctly, you'll want to use the Devise redirect helpers:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
user_add_path
end
end
I don't understand is this:
I should redirect to devise controller again
Devise controllers are split into SessionsController, RegistrationsController, PasswordsController, ConfirmationsController & UnlocksController.
Which one would you like to redirect to?
My hunch, and this is strengthened after reading your comments, is you want to redirect to the UsersController, like this:
#config/routes.rb
resources :users, only: :show do
get :add
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def add
//declarations here
end
def show
//declarations here
end
end
This should help you