ユーザーが自分のメールアドレスでログインできるようにするための最良の方法は何ですかORユーザー名?認証に監視員+工夫を使用しています。おそらくdeviseがすでにこの機能を提供しているのでしょうか?config/initializers/devise.rbのように書いてください:
config.authentication_keys = [ :email, :username ]
サインインにユーザー名と電子メールの両方を要求するため。単にASCIIアートを使用すると、ビューでは次のようになります。
Username or Email:
[____________________]
Password:
[____________________]
[Sign In]
問題の解決策を見つけました。私はそれにはまったく満足していません(イニシャライザでこれを指定する方法があります)が、今のところは機能します。ユーザーモデルに次のメソッドを追加しました。
def self.find_for_database_authentication(conditions={})
find_by(username: conditions[:email]) || find_by(email: conditions[:email])
end
@sguhaと@Chetanが指摘したように、 別の素晴らしいリソースが公式のdev wikiで利用可能です 。
def self.find_for_authentication(conditions)
conditions = ["username = ? or email = ?", conditions[authentication_keys.first], conditions[authentication_keys.first]]
# raise StandardError, conditions.inspect
super
end
ユーザー名フィールドがすでに追加されていることを確認し、attr_accessibleにユーザー名を追加します。ユーザーにログイン仮想属性を作成します
1)attr_accessorとしてログインを追加します
# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login
2)attr_accessibleにログインを追加します
attr_accessible :login
Deviseにauthentication_keysで:loginを使用するように指示します
Config/initializers/devise.rbを次のように変更します。
config.authentication_keys = [ :login ]
ユーザーでDeviseのfind_for_database_authenticationメソッドを上書きする
# Overrides the devise method find_for_authentication
# Allow users to Sign In using their username or email address
def self.find_for_authentication(conditions)
login = conditions.delete(:login)
where(conditions).where(["username = :value OR email = :value", { :value => login }]).first
end
ビューを更新するプロジェクトにDeviseビューがあることを確認して、カスタマイズできるようにします
remove <%= f.label :email %> remove <%= f.email_field :email %> add <%= f.label :login %> add <%= f.text_field :login %>
Platforma Tec(開発者)は、コントローラーにプラグインするのではなく、基盤となるWarden認証戦略を使用するgithub wikiにソリューションを投稿しました。
(以前の回答にはリンクが壊れていたが、これはこのリソースにリンクすることを意図していたと思う。)
https://Gist.github.com/867932 :すべてのための1つのソリューション。サインイン、パスワードを忘れた、確認、ロック解除の手順。
squeel gemを使用すると、次のことができます。
def self.find_for_authentication(conditions={})
self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
end
私はこのように書いて、うまくいきました。 「ugい修正」であるかどうかはわかりませんが、より良い解決策を思い付くなら、お知らせします...
def self.authenticate(email, password)
user = find_by_email(email) ||
username = find_by_username(email)
if user && user.password_hash = BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
私はこれにクイックハックを使用して、デバイス固有のコードの変更を避け、特定のシナリオに使用します(特に、モバイルアプリがサーバー上にユーザーを作成できるAPIに使用します)。
Before_filterをすべてのデバイスコントローラーに追加し、ユーザー名が渡される場合、ユーザー名( "#{params [:user] [:username]} @ mycustomdomain.com")から電子メールを生成し、ユーザーを保存します。他のすべての呼び出しについても、同じロジックに基づいて電子メールを生成します。 before_filterは次のようになります。
def generate_email_for_username
return if(!params[:user][:email].blank? || params[:user][:username].blank?)
params[:user][:email] = "#{params[:user][:username]}@mycustomdomain.com"
end
また、usersテーブルにユーザー名を保存しているので、@ mycustomdomain.comで終わる電子メールを持つユーザーがユーザー名を使用して作成されたことがわかります。
MongoDB(MongoIdを使用)を使用している場合、異なるクエリを実行する必要があります。
def self.find_for_database_authentication(conditions={})
self.any_of({name: conditions[:email]},{email: conditions[:email]}).limit(1).first
end
それだけでオンラインのどこかになります。
Rails @paddeの答えをリファクタリングするソリューションです。ActiveRecordのfind_byを使用して呼び出しを簡素化し、正規表現に基づいて呼び出しが1つのみであることを確認し、それを許可する場合は数値IDもサポートします(電子メールの正規表現は、このコンテキストで必要なだけ簡単です。ユーザー名バリデーターで@文字が許可されていないことを前提として、@の存在を確認するだけです。
def self.find_for_database_authentication(conditions={})
email = conditions[:email]
if email =~ /@/
self.find_by_email(email)
elsif email.to_s =~ /\A[0-9]+\z/
self.find(Integer(email))
else
self.find_by_username(email])
end
end
Wikiと@akuの答えのように、ここで:emailを使用する代わりにattr_accessibleとauthentication_keysを使用して新しい:loginパラメーターを作成することもお勧めします。 (簡単な修正を示すために、この例では:emailのままにしました。)