Reflexões sobre o login usando nome de usuário ou endereço de e-mail com o Devise

Devise é uma das bibliotecas mais polarizadas no ecossistema Rails – você ama ou odeia. Eu sou um fã; tendo usado para vários projetos ao longo de sua evolução e experimentando algumas alternativas (incluindo a minha própria), eu realmente não posso culpá-lo.

Uma coisa que me irrita, entretanto, é o uso do #devise_controller?método e o padrão de customização de seu comportamento inserindo código ApplicationController.

Se você seguir o manual oficial sobre como permitir que os usuários façam login usando o nome de usuário ou a senha, você acabará com algo assim em ApplicationController:

before_filter :configure_permitted_parameters,
:if => :devise_controller?

protected


def configure_permitted_parameters
# ...
end

Essa lógica é necessária para apenas um punhado de ações em um controlador ( DeviseController), mas acabamos com um before_filterque verifica #devise_controller?antes de cada ação em seu aplicativo. É certo que as consequências disso são mínimas, mas não é um bom padrão para repetir e geralmente é um projeto orientado a objetos ruim.

Graças ao poder do Ruby e ao açúcar sintático fornecido por ActiveSupport::Concern, temos uma boa alternativa:

# config/initializers/devise.rb

module MyPermittedParameters
extend
ActiveSupport::Concern

included
do
before_filter
:configure_permitted_parameters
end

protected


def configure_permitted_parameters
...
end
end

DeviseController.send :include, MyPermittedParameters

Enquanto selecionamos o guia vinculado acima, por que não usar Arel em vez de SQL bruto ao substituir #find_first_by_auth_conditions:

def self.find_first_by_auth_conditions(warden_conditions)
conditions
= warden_conditions.dup

if login = conditions.delete(:login)
where
(conditions).
where
(arel_table[:username].lower.eq(login.downcase).or(
arel_table
[:email].lower.eq(login.downcase))).first
else
where
(conditions).first
end
end