2012-05-10 22 views
10

W ten sam sposób, w jaki większość stron internetowych działa, miałem przechowywać "UsErNaMe" w bazie danych, ale pozwól użytkownikom logować się przy użyciu "username".Devise: Pozwól użytkownikom na rejestrację jako "UsErNaMe", ale zaloguj się przy użyciu "username"

Jest to dość oczywista i niezbędna funkcja, a wiele osób zdaje się ją zadawać, ale rozwiązanie, na które natrafiłem, wydaje się być odłączone od własnej dokumentacji Devise.

Na przykład, rozważmy tę blogu: http://anti-pattern.com/2011/5/16/case-insensitive-keys-with-devise

[...] to prawdopodobnie napotkasz problem, że niektórzy użytkownicy lubią wpisać pewnych liter w swoich loginów (e-mail i/lub nazwy użytkownika) wielkimi literami, jednak oczekiwać, że jest wielkość liter, gdy próbują zalogować się a. nie nieuzasadnione żądania [...]

cool! To jest to czego chce.

Jego rozwiązanie:

# config/initializers/devise.rb 
Devise.setup do |config| 
    config.case_insensitive_keys = [:email, :username] 
end 

To rozwiązanie Trzymam ustalenia. Ale tutaj jest dokumentacja dla tej opcji config:

# Configure which authentication keys should be case-insensitive. 
# These keys will be downcased upon creating or modifying a user and when used 
# to authenticate or find a user. Default is :email. 
config.case_insensitive_keys = [ :username, :email ] 

W szczególności: „Te klucze zostaną downcased na tworzenie/modyfikowanie użytkownika.” Innymi słowy, nazwa użytkownika jest zapisywana w bazie danych.

Aby sprawdzić:

User.create username: "UsErNaMe", password: "secret", email: "[email protected]" 
#=> <User username="username"...> 

jestem brakuje czegoś boleśnie oczywiste?

Odpowiedz

10

Od devise wiki: należy zastąpić metodę devise find_first_by_auth_conditions w swoim modelu.

ActiveRecord przykład:

def self.find_first_by_auth_conditions(warden_conditions) 
    conditions = warden_conditions.dup 
    if login = conditions.delete(:login) 
    where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first 
    else 
    where(conditions).first 
    end 
end 

OR lower(email) = :value można usunąć część, jeśli nie trzeba zbyt uwierzytelniania za pośrednictwem poczty elektronicznej.

W ten sposób nie trzeba wyświetlać username w case_insensitive_keys i nie zostanie on usunięty w bazie danych.

+0

To oczywiście zadziała tylko wtedy, gdy zadeklarujesz: wirtualny atrybut logowania w modelu użytkownika, ustaw jako narzędzie: authentication_keys => [: login] i użyj tego atrybutu w formularzu logowania. –

+6

również, chociaż zezwalasz na uwzględnianie wielkości liter w bazie danych, chcesz się upewnić, że unikalność nie uwzględnia wielkości liter, w przeciwnym razie zezwalasz zarówno na nazwę użytkownika, jak i na nazwę użytkownika, ale wyszukiwanie najpierw na niższym spowoduje ich zwielokrotnienie przy pobieraniu. Więc dodaj validates_uniqueness_of: username,: case_sensitive => false –

+0

Działa. Również dobra sugestia, viktor. – danneu

Powiązane problemy