Por razões históricas, meu importador do Google+ importou usuários no Nível de Confiança 1 (TL1) para dar uma vantagem aos refugiados do Google+. Eles são importados com endereços de e-mail .invalid, e nós corrigimos isso quando eles fazem login e são conectados ao seu registro de usuário existente por seu ID do Google através da autenticação do Google.
Mas agora meu grupo trust_level_1 está inchado com milhares de usuários que ainda não seguiram seu conteúdo e, se eles aparecerem depois de alguns anos (como às vezes continuam a fazer), não há razão particular para entrarem como usuários Básicos; eles deveriam ser usuários Novos. O bootstrapping já passou há muito tempo. Eu gostaria de rebaixar esses usuários que nunca fizeram login para TL0 até que eles apareçam e deem uma olhada, e apenas depender do processo normal de promoção.
Eu tentei isso no console Rails:
User.where(trust_level: 1) do |u|
u.change_trust_level!(TrustLevel[0]) if !Email.is_valid?(u.primary_email&.email)
u.save!
end
Levou minutos consumindo uma CPU inteira, mas não fez nada. (Eu tentei outras variações no caminho, como if !u.primary_email.is_valid? e if !Email.is_valid?(u.primary_email) e sei que o problema real é que eu mexo com Ruby uma vez por ano ou mais…) Tenho certeza de que estou perdendo algo óbvio para os outros. Agradeceria uma dica se alguém puder dar uma!
User.where(trust_level: 1).each do |u|
u.change_trust_level!(TrustLevel[0]) if !Email.is_valid?(u.primary_email&.email)
u.save!
end
Isso derrubou meu site enquanto estava em execução com muita E/S e ainda não fez nenhuma alteração. Então, ainda estou fazendo algo errado e não estou um pouco preocupado em continuar tentando isso no sistema ativo.
Descobri que é isso que is_valid? não significa. Então, agora estou procurando a string literal em vez disso, e testei isso imprimindo o endereço de e-mail. Também vejo que change_trust_level já salva o usuário, então não preciso fazer isso duas vezes.
User.where(trust_level: 1).each do |u|
if u.primary_email&.email.end_with?(".invalid")
u.change_trust_level!(TrustLevel[0])
end
end
Mas o número de usuários em trust_level_1 ainda não muda, então ainda estou perdendo algo importante.
Você poderia usar a tarefa de administração em massa neste caso?
Embora eu tenha acabado de testar seu segundo código e ele funcionou para mim em meu usuário de teste (email: test_thirteen@here.invalid, era TL1 e agora é TL0).
User.where(trust_level: 1).each do |u|
if u.primary_email&.email.end_with?(".invalid")
u.change_trust_level!(TrustLevel[0])
end
end
Eu começaria com o modelo UserEmail e encontraria aqueles com “inválido” em seus endereços de e-mail e iteraria sobre eles, mas isso não é algo que eu possa descobrir exatamente no meu telefone.
Se esses endereços com “inválido” neles fossem realmente inválidos, então eles não poderiam ser salvos.
Eu promovi manualmente alguns usuários que já eram bem conhecidos pelos membros existentes da comunidade, então um recálculo em massa não faria o que eu queria. (Eu tinha encontrado essa página enquanto pesquisava.)
Essa última ação estava funcionando, como funcionou para você. Meu problema era que eu estava olhando para a página de visão geral dos grupos /g e atualizando-a, procurando que a contagem do grupo trust_level_1 diminuísse. Ela não estava exibindo uma mudança na contagem enquanto eu a executava, então a interrompi com Control-C. Esta manhã, o grupo trust_level_1 agora tem milhares de membros a menos exibidos nessa página. Então, agora percebo que a contagem ali é em cache, e eu deveria ter clicado naquele cartão e olhado a contagem na página /g/trust_level_1.
Agora entendo que eu deveria ter seguido com Group.ensure_consistency! para reparar as contagens nessa página.
Aqui está tudo, expresso de forma mais compacta e idiomática:
User.where(trust_level: 1).each do |u|
u.change_trust_level!(TrustLevel[0]) if u.primary_email&.email.end_with?(".invalid")
end
Group.ensure_consistency!
Acontece que tenho um registro de alguns usuários com apenas um e-mail inválido que usaram o site e atenderam aos requisitos do TL1. Não sei como isso aconteceu, mas por enquanto não me importo. Tudo o que realmente me importo é cuidar da maioria de milhares, sem me preocupar com as poucas exceções. Se isso acontecer com mais alguém, isso funcionou para mim:
User.where(trust_level: 1).each do |u|
begin
u.change_trust_level!(TrustLevel[0]) if u.primary_email&.email.end_with?(".invalid")
rescue
end
end
Group.ensure_consistency!
def import_google_user(id, name)
if !@emails[id].present?
google_user_info = UserAssociatedAccount.find_by(provider_name: 'google_oauth2', provider_u
id: id.to_i)
if google_user_info.nil?
# cria novo usuário do google no sistema; espera-se que este usuário seja mesclado
# quando eles posteriormente fizerem login com autenticação do google
# Observe que, como o endereço de e-mail não está incluído nos dados do G+, nós
# não sabemos se eles já têm outra conta que ainda não está associada
# ao google ooauth2. Se eles não fizerem login, eles terão um
# endereço @gplus.invalid associado à sua conta
email = "#{id}@gplus.invalid"
Isso significa que eu só me importo com primary_email e não preciso começar com UserEmail. Comecei por esse caminho antes de perceber que qualquer coisa que mudasse isso para não ser o primary_email me faria não querer mudá-los de qualquer maneira. Então, aqui são especificamente usuários cujo único (portanto, primário) e-mail termina literalmente com .invalid — que é o que eu fiz.