I am working on a project and I am facing a problem which I tried to solve but no progress.
All these happened when I started to implement Forgot Password
functionality for resetting password. I have a User Model
which has validations for password
and password_confirmation
. I used these for registration and are working fine.
But for this functionality I am using a new controller called PasswordResets
. I am generating a string called password_reset_token
for my users table. And there is password_reset_sent_at
which records the time a user asks for a reset. The process goes like this;
1) The User clicks
Forgot Password
?2) He is redirected to a page where he is asked to enter his email.
3) Controller checks if the email is present in database, if yes then ;
3.1) I generate a randompassword_token
by usingSecureRandom
and also time when he started the request.
3.2) Now the save happens here for sending the mail to user. Here the problem occurs. Thepassword_reset_token
is not getting saved into table.
The reason behind that is I am using validations for password
and password _confirmation
in User.rb
. Here the action taking place is :update
, so on update the record is asking for password
and password_confirmation
to be sent along with password_reset_token
and the time.
But I tried solving by keeping validations as :on => :create
, now it is working well but when I use the link for resetting my validations will not work for password
and password_confirmation
. This is like a deadlock for me. I know this is bit confusing, I am pasting some code to understand the problem.
My PasswordResets Controller
create action:
def create
user= User.find_by_email(params[:email])
if user
user.send_password_reset
UserMailer.password_reset(self).deliver
flash[:success] = "Email sent with password reset instructions."
redirect_to root_url
else
flash[:error] = "Email doesn't exit."
render 'password_resets/new'
end
end
My User Model
(user.rb)
class User < ActiveRecord::Base
has_secure_password
EMAIL_REGEX = /\A[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}\Z/i
validates_confirmation_of :password_confirmation
validates :username, :presence => true,
:uniqueness => true,
:length => {:within => 8..25}
validates :email, :presence => true,
:uniqueness => true,
:format => EMAIL_REGEX
validates :password, :length => {:within => 8..25}
validates :password_confirmation, :presence => true
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
end
The error is shown at save!
in send_password_reset
. I am attaching an image.
I know the problem can be solved by using :on=>:create
for validations as :update
request is taking place. But when I get confirmation link in my console and use it, the validations for password and password_confirmation dont work as the action here is :update
. This is like a deadlock.
I am really grateful to anyone who help me out from this maze.
Thank you.
You can Skip Validations using following eg.
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
self.save(validate: false)
UserMailer.password_reset(self).deliver
end