Couldn't find User without an ID - ruby-on-rails

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

Devise - creating users only by admin

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).

Rails 4 - Using namespaced STI models with devise

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

Direct user on sign-in in devise rails

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!

Devise invalid forgot password URL

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
)

Redirecting to the devise controller after successfull login

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

Resources