Rails unable to override Devise Passwords Controller - ruby-on-rails

I am trying to override the passwords controller in Devise and when changing the devise_for :users routes in my routes.rb file the routes are not being populated when running rails routes.
I have a file called users/passwords_controller.rb with a puts in there as an example.
class User::PasswordsController < Devise::PasswordsController
def create
puts 'creating user profile'
super
end
end
Here is the route defination.
devise_for :users, controllers: {
sessions: 'user/sessions',
passwords: 'user/passwords',
registrations: 'user/registrations'
}
The rails routes command returns these and only these devise routes.
new_user_session GET /users/sign_in(.:format) user/sessions#new
user_session POST /users/sign_in(.:format) user/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) user/sessions#destroy
cancel_user_registration GET /users/cancel(.:format) user/registrations#cancel
new_user_registration GET /users/sign_up(.:format) user/registrations#new
edit_user_registration GET /users/edit(.:format) user/registrations#edit
user_registration PATCH /users(.:format) user/registrations#update
PUT /users(.:format) user/registrations#update
DELETE /users(.:format) user/registrations#destroy
POST /users(.:format) user/registrations#create
When running rails routes I would expect to see the passwords routes, however they are not there and this leads to 404's when trying to hit these resources. I am unable to find any documentation about this behavior anywhere. I am currently running Ruby version 3.1.2, Rails version 7.0.4.2, and Devise version 4.8.1.
I have looked into this post, however it does not describe my problem and is over 10 years old at this point.

Make sure you have :recoverable in you User model:
class User < ApplicationRecord
devise :database_authenticatable, :recoverable # there's also :trackable, :validatable, :confirmable
end
This enables the passwords routes.

Related

Devise routes do not skip

I need some help here.
I'm trying to eliminate the route paths destroy and cancel from the Devise registerable module but I haven't been succeed.
Route.rb
devise_for :users, :skip => [:registrations], controllers: {
sessions: 'users/sessions',
confirmations: 'users/confirmations',
passwords: 'users/passwords'
}
get '/users/sign_up', to: 'users/registrations#new'
get '/users/edit', to: 'users/registrations#edit'
post '/users', to: 'users/registrations#create'
put '/users', to: 'users/registrations#update'
Model.rb
devise :database_authenticatable, :registerable,
:recoverable, :trackable, :validatable, :confirmable
Rails route
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
As you can see in Rails routes, Devise is creating the route paths devise/registrations even when set the option :skip up for the devise_for method. Someone already face this problem?
Thanks in advance.
Along with skip also add skip_helpers: true.
skip_helpers: skip generating Devise url helpers like new_session_path(#user).
This is useful to avoid conflicts with previous routes and is false by default.
It accepts true as option, meaning it will skip all the helpers for the controllers
given in :skip but it also accepts specific helpers to be skipped:
devise_for :users, skip: [:registrations, :confirmations], skip_helpers: true
devise_for :users, skip_helpers: [:registrations, :confirmations]
Source:
From devise Documentation
https://github.com/plataformatec/devise/blob/master/lib/devise/rails/routes.rb#L160

Why users/passwords/new is redirect to root in Rails4?

I'm now using Devise gem in a Ruby application.
It seems a password method doesn't work because in somehow, devise controller is a bit modified. When I typed /users/password/new, it goes back to a root.
I followed a tutorial but now I'm stuck at this really important method that I have to provide to the people.
The passwords_controller.rb file is located in controllers/users/password_controller.rb.
And the code is
class Users::PasswordsController < Devise::PasswordsController
prepend_before_filter :require_no_authentication
# Render the #edit only if coming from a reset password email link
append_before_filter :assert_reset_token_passed, only: :edit
# GET /resource/password/new
def new
self.resource = resource_class.new
end
# POST /resource/password
def create
self.resource = resource_class.send_reset_password_instructions(resource_params)
yield resource if block_given?
if successfully_sent?(resource)
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with(resource)
end
end
( which is a typical devise controller content )
My user.rb model goes as follow.
...
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:google_oauth2] #, :confirmable
...
I have view files in this directory.
views/users/passwords/create.html.erb, edit.html.erb, new.html.erb
views/users/sessions/new.html.erb
views/users/registrations/edit.html.erb, create.html.erb
Routes file goes like this
devise_for :users, controllers: { passwords: "users/passwords", sessions: "users/sessions", registrations: "users/registrations", omniauth_callbacks: "users/omniauth_callbacks" }
Whenever I type "http://localhost:3000/users/password/new", it goes back to root.
This is my route file.
new_user_session GET /users/sign_in(.:format) users/sessions#new
user_session POST /users/sign_in(.:format) users/sessions#create
destroy_user_session GET /users/sign_out(.:format) users/sessions#destroy
user_omniauth_authorize GET|POST /users/auth/:provider(.:format) users/omniauth_callbacks#passthru {:provider=>/google_oauth2/}
user_omniauth_callback GET|POST /users/auth/:action/callback(.:format) users/omniauth_callbacks#:action
user_password POST /users/password(.:format) users/passwords#create
new_user_password GET /users/password/new(.:format) users/passwords#new
edit_user_password GET /users/password/edit(.:format) users/passwords#edit
PATCH /users/password(.:format) users/passwords#update
PUT /users/password(.:format) users/passwords#update
cancel_user_registration GET /users/cancel(.:format) users/registrations#cancel
user_registration POST /users(.:format) users/registrations#create
new_user_registration GET /users/sign_up(.:format) users/registrations#new
edit_user_registration GET /users/edit(.:format) users/registrations#edit
PATCH /users(.:format) users/registrations#update
PUT /users(.:format) users/registrations#update
DELETE /users(.:format) users/registrations#destroy
POST|GET /:controller(/:action(/:id))(.:format) :controller#:action
root GET / landings#index
The log I got when I go to localhost:3000/users/password/new goes like this.
Started GET "/users/password/new" for ::1 at 2015-10-06 04:11:58 +0900 Processing by Users::PasswordsController#new as HTML Redirected to localhost:3000 Filter chain halted as :is_login rendered or redirected Completed 302 Found in 2ms (ActiveRecord: 0.0ms) This is a log that I got right after I posted the address
If you guys have any hint, please let me know!!
Best
I fix it by append /users/password/edit?reset_password_token=aaaaaa
maybe it is the devise bug .

undefined method `index_path' using relation

I get the following error using device and carrierwave gem:
undefined method `user_media_index_path'
.Showing .../user_medias/new.html.erb where line #3 raised:
I have added index on user_id in user_media model
I have successfully implemented file upload for for single model but I don't know how to do it with a seperate module.
new.html
form_for #media, :html =>{:multipart =>true} do |f|
Upload an Image f.file_field :image
f.submit
end
This is the user model generated using the device gem:
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :user_media, dependent: :destroy
end
its the model to store the user medias like images,etc i;m using this now only for images
but for future to add more types of media i have created this user_media model
user_media.rb
class UserMedia < ActiveRecord::Base
attr_accessible :anudio, :image, :video
belongs_to :user
mount_uploader :image, MediaUploader
end
This is where its get redirected to when asked for create action for uploading the image
user_medias_controller
class UserMediasController < ApplicationController
def new
#media = UserMedia.new
end
def create
#media=current_user.user_media.build(params[:media])
if #media.save
render'index'
else
render'new'
end
end
end
The routing details are:
routes.rb
Projectx::Application.routes.draw do
get "dashboard/index"
resources :dashboard, :UserMedias
get "home/index"
devise_for :users
root :to => 'home#index'
match 'uploder' =>'UserMedias#new'
rake routes output this all after adding resources suggested by #peter
dashboard_index GET /dashboard/index(.:format) dashboard#index
GET /dashboard(.:format) dashboard#index
POST /dashboard(.:format) dashboard#create
new_dashboard GET /dashboard/new(.:format) dashboard#new
edit_dashboard GET /dashboard/:id/edit(.:format) dashboard#edit
dashboard GET /dashboard/:id(.:format) dashboard#show
PUT /dashboard/:id(.:format) dashboard#update
DELETE /dashboard/:id(.:format) dashboard#destroy
user_medias GET /user_medias(.:format) user_medias#index
POST /user_medias(.:format) user_medias#create
new_user_media GET /user_medias/new(.:format) user_medias#new
edit_user_media GET /user_medias/:id/edit(.:format) user_medias#edit
user_media GET /user_medias/:id(.:format) user_medias#show
PUT /user_medias/:id(.:format) user_medias#update
DELETE /user_medias/:id(.:format) user_medias#destroy
home_index GET /home/index(.:format) home#index
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root / home#index
uploder /uploder(.:format) user_medias#new
the error points to a missing route in your routes file. add this to your routes
resources :user_medias

Devise 2.0.4, Rails 3.2.3 - After creating user account I am redirected to root and can't access other routes

I'm coming from Sinatra to Rails and still quite new to Rails. My problem is that after I create a User account I am just directed to the index.html page in the /public folder and can't seem to access any other routes, I can't sign_out the user and I can't add another user.
I am using the devise gem to manage my user model and authentication. After installing the gem I followed the instructions on the devise github page.
ie:
rails generate devise:install
I also added to the 'config/environments/development.rb' file
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
and I added to the 'config/routes.rb' file
root :to => "home#index"
and I added to the 'app/views/layouts/application.html.erb' file
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
Then I ran
rails generate devise User
And finally
rake db:migrate
Here is my user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
end
Then I navigated to "/users/sign_up" and I entered an email and password after which I was redirected to the index.html page in the public folder.
The problem is I just seem to be stuck there. '/users/sign_out' yields
Routing Error
No route matches [GET] "/users/sign_out"
Try running rake routes for more information on available routes.
And running 'rake routes' yields
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root / home#index
Seems like '/users/sign_up' should be a working route.
I am wondering if the problem is that there is no email service setup and this account is trying to be validated trough email? If so, how do I disable that?
Thanks! And let me know if you need more information or for me to clarify something.
===============UPDATE===================
The 'users/edit' route does work and I think possibly the problem lies in the fact that the route that is setup for 'users/sign_out' is a DELETE route. I forget the terminology about this, but I know that there is some sort of trickery in making a DELETE route out of a GET route. So is this where my problem lies?
You can do one of two things here.
Create a link to do the logout, something like this:
<%= link_to "Logout", destroy_user_session_path, method: :delete %>
Or add an additional route like this to your routes.rb file:
devise_for :users, :skip => [:sessions]
as :user do
get 'signin' => 'devise/sessions#new', :as => :new_user_session
post 'signin' => 'devise/sessions#create', :as => :user_session
get 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session
end
The above example is from https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes
To sign out, you should be calling:
destroy_user_session_path
Devise stores sessions, and DELETE just removes your session.
For the routing error, can you post up your HomeController?
And for the edit, are you calling:
edit_user_registration_path
A few moments ago I was having this problem and instead of looking for sites and more sites, it was when i stop here and one of the codes shown above is also shown below worked fine for me thanks
devise_for :users, :skip => [:sessions]
as :user do
get 'signin' => 'devise/sessions#new', :as => :new_user_session
post 'signin' => 'devise/sessions#create', :as => :user_session
get 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session
end

Devise after_sign_in_path_for ... sending to .... root_path - query

I need help with a routes issue with devise authentication gem to redirect to a custom page after successful login so as to create a new record by entering a test person name and age ( test data )
I am using Rails 3 with devise version 1.4.9
My routes are as below
new_user_session GET /users/sign_in(.:format) {:action=>"new", :controller=>"devise/sessions"}
user_session POST /users/sign_in(.:format) {:action=>"create", :controller=>"devise/sessions"}
destroy_user_session DELETE /users/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"}
user_password POST /users/password(.:format) {:action=>"create", :controller=>"devise/passwords"}
new_user_password GET /users/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"}
edit_user_password GET /users/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"}
PUT /users/password(.:format) {:action=>"update", :controller=>"devise/passwords"}
cancel_user_registration GET /users/cancel(.:format) {:action=>"cancel", :controller=>"devise/registrations"}
user_registration POST /users(.:format) {:action=>"create", :controller=>"devise/registrations"}
new_user_registration GET /users/sign_up(.:format) {:action=>"new", :controller=>"devise/registrations"}
edit_user_registration GET /users/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"}
PUT /users(.:format) {:action=>"update", :controller=>"devise/registrations"}
DELETE /users(.:format) {:action=>"destroy", :controller=>"devise/registrations"}
testers GET /testers(.:format) {:action=>"index", :controller=>"testers"}
POST /testers(.:format) {:action=>"create", :controller=>"testers"}
new_tester GET /testers/new(.:format) {:action=>"new", :controller=>"testers"}
edit_tester GET /testers/:id/edit(.:format) {:action=>"edit", :controller=>"testers"}
tester GET /testers/:id(.:format) {:action=>"show", :controller=>"testers"}
PUT /testers/:id(.:format) {:action=>"update", :controller=>"testers"}
DELETE /testers/:id(.:format) {:action=>"destroy", :controller=>"testers"}
root / {:controller=>"testers", :action=>"index"}
In applications controller i tried to override the method like below but to no avail i still get routed back to tester index
class ApplicationController < ActionController::Base
protect_from_forgery
def after_sign_in_path_for(resource)
new_tester_path
end
end
In my routes.rb file i have the below lines
Testing::Application.routes.draw do
devise_for :users
resources :testers
root :to => 'testers#index'
While much of the code was done with scaffolding I was still not be able to figure how to redirect to new_tester_path or route /testers/new after successful sign_in by user email and password.
Can someone please let me know what i am missing..... while writing the override function, I would like to know the exact route i need to specify.
While testing i tried something stupid like this but the google page is also not opening ... :(
class ApplicationController < ActionController::Base
protect_from_forgery
helper ApplicationHelper
def after_sign_in_path_for(resource)
"www.google.com"
end
def after_sign_up_path_for(resource)
"www.google.com"
end
def after_update_path_for(resource)
"www.google.com"
end
Just use this snippet:
class ApplicationController < ActionController::Base
def after_sign_in_path_for(user)
user_url(user)
end
end
Try setting user_return_to path in session:
session['user_return_to'] = new_tester_path
You can do it in a controller derived from Devise::SessionsController
The Devise documentation explains all the steps to redirect to a specific page on successful sign in. By combine the techniques, you can redirect a user to many places after successful sign in.
Here is the resume:
You can do this in a controller you inherit from Devise::SessionsController - first, in controllers/users/sessions_controller.rb:
module Users
class SessionsController < Devise::SessionsController
def new
if params[:redirect_to].present?
self.resource = resource_class.new(sign_in_params)
store_location_for(resource, params[:redirect_to])
end
super
end
end
end
In config/routes.rb, you would have also added:
devise_for :users, controllers: {sessions: 'users/sessions'}
And you must add a custom after_sign_in_path_for in your ApplicationController
class ApplicationController < ActionController::Base
protected
def after_sign_in_path_for(resource)
stored_location_for(resource) || root_path
end
end
This works in all Devise versions, as I know.
I believe this is an inheritance issue. after_sign_in_path_for is originally defined within Devise::SessionsController. You can override it by making your SessionsController inherit from Devise::SessionsController, and then re-defining it within that controller.
If you are having issues trying to override the after_sign_in_path_for or after_sign_out_path_for helper methods within the ApplicationController of a Rails engine, you may want to check out this answer.
It describes how you'll need to override the SessionsController in your engine instead of the ApplicationController.
You don't seem to be doing anything wrong. Maybe this is a Devise issue.
Can you please try to isolate this on a Rails app and open an issue on Devise ?

Resources