I've done all of the this tutorial: Devise wiki
But when I try to log in I get error in the browser:
SQLite3::SQLException: no such column: users.login: SELECT "users".* FROM "users" WHERE "users"."login" = 'jan12345' ORDER BY "users"."id" ASC LIMIT 1
Where could be a problem? How to debug this?
I don't have login
field on the users
table but I have username
field.
My model file:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
attr_accessor :login
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :expiration_date) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :username, :email, :password, :remember_me) }
end
end
You're sending the login
attribute to the db; you need to make it either username
or email
, which is done with a combination of both a custom attribute & special lookup, as per the docs :
#app/models/user.rb
class User < ActiveRecord::Base
#remove attr_accessor :login (it just makes getter/setter methods which we do manually below)
protected
def login=(login)
@login = login
end
def login
@login || self.username || self.email
end
private
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions.to_h).first
end
end
end
--
You've done a great job with the sanitizer etc -- what you're doing is taking a single "login" attribute & making Devise use either login
, username
or email
to find the User
record.
At present, the error says users.login
cannot be found -- this means your Devise
install is looking up login
(which isn't in your database), when it should be searching through username
and email
WITH the login
attribute.
The second bit of code ( self.find_for_database_authentication
) performs a lookup for Devise
. If you read the query, it takes the login
attribute and sets it to looking up either username
or email
. This is missing from your implementation and should be added.
After adding, remember to restart your server.
Update
Your attr_accessor
should be in your model (yours is in your controller).
All it does is define a setter
and getter
method for the attribute you define. It's most commonly referred to as a "virtual" attribute , as it's not saved in the database.
I could tell you about setter
/ getter
methods if required, I'll leave it for now to prevent confusion
In your initializer/devise.rb , write the below code:
config.authentication_keys = [ :username ]
In application controller , write the below code:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username) }
end
You do not have to do that much code,
You can check from https://stackoverflow.com/a/55184048/9490901 ,
only replace contact_number to username :
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.