Substituindo user_guardian.rb em um plugin (sem necessidade de fork!)

Ei, desculpe pela pergunta de iniciante aqui. Tenho lido a documentação, mas preciso de alguma orientação, por favor.

Forki o Discourse e fiz minhas próprias alterações, das quais gostaria de fazer meu próprio deploy. O guia de contribuição explica como fazer alterações e enviar um PR, mas, neste caso, não quero enviar um PR. Gostaria apenas de aplicar minha pequena alteração e fazer uma instalação do Discourse a partir dela. Achei que o jeito de fazer isso fosse alterar esta linha para o meu próprio repositório:

Fiz isso e executei uma instalação, mas as alterações que fiz não estão aparecendo, então claramente estou fazendo algo errado. Alguma ideia? Obrigado!

EDIT:
Para transparência, e caso alguém tenha uma maneira mais fácil de fazer isso, tudo o que estou tentando fazer é permitir que usuários anônimos alterem seus nomes de usuário quando entram no modo anônimo. É tão simples quanto mudar false para true nesta linha:

Se houver uma maneira melhor, estou todo ouvidos. Mas é só isso que preciso ativar. Tenho habilidade com Python, Java e muitas outras coisas de back-end, mas não sei nada de Ruby/JavaScript/HTML/etc.

EDIT2:
Conforme um post que vi em outro lugar, atualizei o app.yml da seguinte forma:

run:
- exec:
 cd: /var/www/discourse
 cmd:
    - sudo -u discourse git remote set-url origin https://github.com/my/forked/discourse.git
    - sudo -u discourse git fetch origin
    - sudo -u discourse git checkout origin/master

Ainda não funcionou após reconstruir o app. Inicia normalmente, mas parece que minhas alterações não estão presentes.

Não é possível encapsular suas alterações em um plugin e usá-lo em vez disso?

5 curtidas

Todos que fizeram isso ficaram muito arrependidos. E você não conseguirá muita ajuda aqui.

O que quer que esteja fazendo, faça em um plugin.

10 curtidas

Ok. Alguma ideia de como eu poderia fazer isso via plugin?

Olá @leighno5

Minha opinião para você, baseada na minha experiência pessoal, é que escrever plugins em Ruby para fazer o que você está fazendo no seu “fork” é muito mais fácil quando já entendemos Ruby e Rails o suficiente para criar facilmente um plugin para o Discourse (ou modificar qualquer classe do Rails).

Se não entendemos Rails e Ruby o suficiente para escrever um plugin para o Discourse, na minha experiência, fazer um fork do Discourse e mexer no núcleo é “equivocado”.

Acho que a analogia é esta (desculpe pela simplicidade da ideia):

“Alguém acha difícil caminhar; então decide correr em vez disso.”

Deixe-me explicar, se você não se importar:

Antes de começar a escrever aplicações em Rails (nada a ver com o Discourse) e tentar criar plugins para o Discourse, eu estava um pouco perdido; e até ficava um pouco irritado com o Discourse, acho. É como quando você quer acertar uma bola de golfe pela primeira vez; ela não vai direto e exige muito trabalho para acertar a bola no meio do fairway. Fazer um fork do Discourse é como pegar o driver grande no campo de prática antes de conseguir fazer chips e putts com os ferros curtos!

Eu tirei um tempo de fora de mexer no Discourse (vários meses atrás) e trabalhei por um tempo construindo, de fato, várias aplicações em Rails do zero; e então (e só então) comecei a desenvolver um conhecimento “instintivo” sobre Rails. Depois disso, quando decidi modificar o Discourse (atualmente estou rodando 6 plugins personalizados que escrevi para produção no Discourse), tudo se tornou intuitivo e plugins que modificavam o núcleo do Ruby ficaram muito simples.

Ruby é muito flexível. Podemos sobrescrever qualquer classe, qualquer objeto. Podemos redefinir todos os aspectos do Ruby. Com alguma experiência, começamos a pensar: “UAU”, não fazia ideia de que Ruby era tão flexível (e poderoso) e começamos a “ficar perigosos”, porque podemos voar como o Superman com Ruby e Rails. Estamos no início da nossa jornada em Ruby e Rails nesse momento, não no fim!

Com o conhecimento em Ruby e Rails que adquiri em 2020, sabendo o que sei agora, eu nunca faria um fork do Discourse e faria mudanças no núcleo do Ruby e do Rails como você está propondo, porque plugins são simplesmente muito fáceis de sobrescrever e modificar classes do Ruby, quando entendemos o básico das classes do Ruby e o básico de metaprogramação.

Acho que o que estou dizendo, desculpe ser tão direto, é que, se alguém acha que precisa mexer no núcleo do Discourse para fazer algumas pequenas mudanças em Ruby; então essa pessoa não entende Ruby e Rails o suficiente; porque, se entendesse, não mexeria no núcleo e apenas escreveria um plugin rápido para sobrescrever as classes e adoraria o monkey-patching.

Por outro lado, se eu quisesse fazer algo maluco e ser miserável, como substituir o EmberJS do Discourse por React e Ant Design, então fazer um fork seria a única opção! No entanto, na minha visão, o “Discourse” não é definido pelas “bibliotecas JavaScript”. O Discourse é definido pelas habilidades da equipe de desenvolvimento principal (as pessoas) e sua atenção aos detalhes, atendimento ao cliente, abordagem de equipe para desenvolvimento de código aberto, seu pipeline de recursos SPA e todo o trabalho duro deles! Seria um pouco maluco (na minha opinião) jogar todo esse poder intelectual fora só porque podemos gostar mais do Ant Design (com React) ou VueJS do que do Ember.

O mesmo é totalmente verdadeiro, ainda mais se vamos apenas modificar o núcleo do Discourse aqui e ali! Seria um pouco “maluco” fazer um fork para isso, jogando fora as “pessoas” que são o “verdadeiro” Discourse (não o código).

Estou falando apenas da minha jornada pessoal em 2020 aprendendo Ruby e Rails. Agora, está ficando fácil (o básico) e eu estou “perigoso”, LOL. Posso “brincar com monkey patch em qualquer coisa”, o que nem sempre é bom; e é para isso que os plugins do Discourse servem.

Mantenha o núcleo sólido como uma rocha e divirta-se “brincando” com o Discourse usando plugins.

Espero que isso ajude.

Nota: enquanto escrevia esta resposta, você escreveu:

Isso meio que prova meu ponto, não acha?

Escrever um “plugin” no Discourse é escrever “código Ruby” (em um nível) e, para outros, vai muito mais fundo (no EmberJS).

Antes de começar a escrever plugins para o Discourse, meu conselho amigável, talvez parecendo sem valor para você, é primeiro desenvolver algumas aplicações em Ruby on Rails. Aprenda seu caminho em Ruby e Rails, pelo menos o básico; depois disso, você terá respondido à sua própria pergunta acima.

Eu estava no telefone esta manhã em uma conferência com um cliente por três horas discutindo uma aplicação em Rails, validações, modelos, etc., e depois estava tirando um descanso após codificar algumas das ações da chamada e li sua postagem.

O caminho mais curto para escrever plugins para o Discourse, na minha opinião, é aprender Rails primeiro.

Espero que isso ajude!

5 curtidas

Aqui está um bom ponto de partida:

3 curtidas

Não, você está exatamente correto. Não tenho nenhuma experiência com Ruby, então, com certeza, não leve a mal!

Já li o guia do plug-in e o revisei algumas vezes, mas, infelizmente, minha ignorância em Ruby continua a me frustrar, e não faço a menor ideia de como escreveria um plug-in que sobrescrevesse aquela pequena parte do código no arquivo user-guardian para permitir que usuários anônimos alterem seus nomes. :confused:

2 curtidas

Olá @leighno5,

Sim, entendo.

Esses tópicos de “HOWTO” sobre plug-ins foram escritos por desenvolvedores extremamente talentosos, com mais de uma década de experiência em programação Rails e Ruby (talvez até mais). Na verdade, alguns desses profissionais estão entre os melhores desenvolvedores de Ruby e JS do mundo.

Tenho 100% de certeza de que todos eles aprenderam Rails e Ruby muito antes de escreverem seu primeiro plug-in para o Discourse.

Na verdade, aprender Rails não é tão difícil; mas é necessário realizar o “rito prático” de construir alguns aplicativos Rails do zero. Não apenas seguir tutoriais no YouTube (o que é bom), mas realmente desenvolver um aplicativo funcional, onde você precise configurar o banco de dados, gerar seus próprios modelos, criar seus próprios controladores, escrever validações de modelos, criar inicializadores, módulos de helpers, realizar migrações (modificações) no banco de dados, trabalhar com Ruby embutido e muito mais.

É realmente muito divertido e representa o “caminho mais curto” para se sentir confortável escrevendo plug-ins (no que diz respeito à parte do Rails; pessoalmente, não trabalho muito com Ember, mas adoro a parte do Rails)!

Além disso, você precisa aprender a usar o console do Rails! O console do Rails é muito divertido e eu o uso todos os dias com prazer!

Hoje, meu cliente favorito e eu estávamos usando o AnyDesk, e ele perguntou: “Podemos ter essa nova visão do Inventário?”. Ele queria me ver fazendo tudo. Depois de colocarmos tudo funcionando, ao final da chamada, ele disse: “Você fez algo no Rails em 30 minutos que levaria várias semanas há algumas décadas!!”. Incrível mesmo, @leighno5. Vá em frente!!

Depois de aprender Rails, você vai dizer “UAU”: escrever plug-ins para o Discourse é bastante fácil, pelo menos na parte de Rails e Ruby!!

Espero ter ajudado.

3 curtidas

Olhe o código existente de #plugin. Há absolutamente muitos deles agora, então há muitos exemplos. Não pule a leitura de trabalhos anteriores para que você possa aproveitá-los.

Parece que você só quer sobrescrever um método, o que é simplesmente um caso de redefini-lo no seu plugin.rb (embora a melhor prática seja, argumentavelmente, separá-lo em seu próprio arquivo por módulo, mas não vale a pena para um único método!)

5 curtidas

Arriscando-me a mostrar ainda mais minha ignorância e aproveitando a gentileza que você já me demonstrou, você estaria disposto a expandir um pouco mais sobre isso? Ou, se você souber de outro exemplo em que alguém tenha sobrescrito um módulo e puder fornecer um link, ficaria grato. Não sou de forma alguma contra o “leia o manual” (RTFM), mas minha falta de compreensão de como o Discourse funciona é frustrante, apesar de todo o tempo que passei revisando vários tutoriais e documentos. E sim, sei que perguntas tão básicas podem parecer que fiz pouco esforço, mas garanto que não é o caso!

3 curtidas

Aqui está um exemplo onde definimos um método no PostGuardian:

Você pode fazer algo semelhante no UserGuardian usando o nome do método existente, o que deve sobrescrevê-lo.

Solução simples (para fazer funcionar, mesmo que não seja robusta):

Basta escrever o código original do método e fazer sua alteração. Ponto negativo: se o Discourse alterar o código, seu plugin pode quebrar a instância.

Solução avançada (solução mais robusta):

Para ganhar pontos extras, você pode tentar usar super para herdar o método original, mas isso não é garantido de funcionar por razões que não detalharei aqui. No entanto, é a melhor prática, pois assim as atualizações desse método no Discourse serão sempre consideradas sem que você precise editar seu plugin.

O Discourse é uma plataforma. Leva tempo para aprendê-la. Apenas vá passo a passo.

6 curtidas

Isso é exatamente o que eu estava preocupado. O método avançado mencionado no seu próximo parágrafo está coberto no guia de como fazer? Existe um bom exemplo simples de como ele é usado em um plugin existente que possa ser utilizado (copiado) na criação de um novo plugin?

Eu não me preocuparia com o método avançado por enquanto. Apenas faça funcionar. Você pode pesquisar sobre Ruby on Rails em geral em outros lugares dos guias online. Um pouco fora do escopo específico do Discourse e deste fórum. Apenas esteja ciente.

1 curtida

Ok, valeu! Digamos que eu escreva um plugin curto. Se entendi corretamente, devo então verificar o código principal a cada atualização e reescrever o plugin se o código principal relevante tiver mudado. É isso? Obrigado.

1 curtida

Isso está correto. Apenas verifique-o ocasionalmente e, especialmente, se começar a apresentar mau funcionamento. O código do Guardian é um pouco mais crítico, pois trata da autorização do site de codificação, então fique atento a ele.

Outra solução é adicionar casos de teste (também conhecidos como specs) e configurar uma tarefa automatizada para executá-los… mas isso fica mais complexo!

2 curtidas

Outra tarefa de bônus é configurar o travis-ci.org para executar os testes do seu plugin, assim você será avisado caso algo quebre.

5 curtidas

Claramente, não é uma tarefa para ser levada de ânimo leve. Gostaria de alterar o(s) modal(is) de login/criar nova conta e remover a imagem do Twitter. Talvez este último seja um projeto melhor para começar. Obrigado.

Se alguém encontrar isso e estiver tão perdido quanto eu, estou fornecendo meu código abaixo, pois consegui fazê-lo funcionar como pretendido. Não modifiquei nenhum arquivo. Simplesmente criei um novo arquivo plugin.rb e coloquei dentro dele o seguinte:

# name: noms
# about: Permite que usuários no Modo Anônimo alterem seus nomes de usuário
# version: 0.1


require_dependency 'guardian'
require_dependency 'guardian/user_guardian'

class ::Guardian
end

module ::UserGuardian
  def can_edit_username?(user)
    return false if SiteSetting.sso_overrides_username?
    return true if is_staff?
    return false if SiteSetting.username_change_period <= 0
    return true if is_anonymous?
    is_me?(user) && ((user.post_count + user.topic_count) == 0 || user.created_at > SiteSetting.username_change_period.days.ago)
  end


  def can_edit_name?(user)
    return false unless SiteSetting.enable_names?
    return false if SiteSetting.sso_overrides_name?
    return true if is_staff?
    return true if is_anonymous?
    can_edit?(user)
  end
end

Isso substitui a classe user_guardian.rb no núcleo do Discourse para permitir que usuários alterem o nome de usuário e o nome de suas contas de usuário anônimo.

Se você comparar o que tenho aqui com o que está em user_guardian.rb no núcleo do Discourse, verá que há um monte de outras coisas com as quais não precisei fazer nada, então as deixei como estavam. Tudo o que precisei foi editar esses dois métodos can_edit_username e can_edit_name, alterando alguns valores de retorno de false para true, e consegui realizar o que precisava.

Certamente há melhorias que poderiam ser feitas, e provavelmente há melhores práticas que pude aprender lendo os posts vinculados aqui e em outros lugares. Mas se você é novo em Ruby como eu e só quer fazer uma alteração muito simples no núcleo, este é um exemplo minimalista funcional do que você precisa fazer.

Muito obrigado às pessoas neste tópico pela paciência, encorajamento e assistência! Em especial a @merefield, que na verdade me ajudou em outro post no passado.

10 curtidas

LOL

Você foi longe desde sua ideia inicial de bifurcar todo o Discourse e abandonar a branch principal para tarefas simples como essas.

Bom trabalho :slight_smile:

4 curtidas

Você seguiu todo o caminho em Install Discourse on Ubuntu or Debian for Development ou apenas trabalhou no seu site de produção e torceu para dar certo?