Sovrascrivere user_guardian.rb in un plugin (nessun fork necessario!)

Ehi, scusa per la domanda da principiante qui. Ho letto la documentazione ma ho bisogno di una guida, per favore.

Ho fatto un fork di Discourse e apportato le mie modifiche, che vorrei poi utilizzare per il mio stesso deployment. La guida al contributo ti spiega come apportare modifiche e inviare una PR, ma in questo caso non voglio fare una PR. Vorrei solo prendere la mia piccola modifica e far funzionare un’installazione di Discourse partendo da quella. Pensavo che il modo per farlo fosse modificare questa riga puntando al mio repository:

L’ho fatto e ho eseguito l’installazione, ma le modifiche che ho apportato non si vedono, quindi chiaramente sto facendo qualcosa di sbagliato. Qualche idea? Grazie!

MODIFICA:
Per trasparenza e nel caso qualcuno abbia un modo più semplice per farlo, tutto ciò che sto cercando di fare è permettere agli utenti anonimi di modificare i propri nomi utente quando entrano in modalità anonima. È semplice come cambiare false in true in questa riga:

Se c’è un modo migliore, sono tutto orecchie. Ma questo è tutto ciò che devo abilitare. Sono esperto di Python, Java e molte altre cose back-end, ma non so nulla di Ruby/JavaScript/HTML/ecc.

MODIFICA 2:
Come indicato in un post che ho visto altrove, ho aggiornato app.yml come segue:

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

Ancora nessun risultato dopo la ricostruzione dell’app. Si avvia correttamente ma le mie modifiche non sono presenti, sembra.

Non è possibile incapsulare le tue modifiche in un plugin e usarlo invece?

5 Mi Piace

Tutti quelli che lo hanno fatto si sono pentiti. E qui non puoi ottenere molto aiuto.

Qualunque cosa tu stia facendo, fallo in un plugin.

10 Mi Piace

Ok. Hai un’idea su come potrei farlo tramite un plugin?

Ciao @leighno5,

Dal mio punto di vista e basandomi sulla mia esperienza personale, scrivere plugin in Ruby per fare ciò che stai facendo nel tuo “fork” è molto più semplice se si parte da un plugin, una volta che si comprende Ruby e Rails a sufficienza da poter scrivere facilmente un plugin per Discourse (o modificare qualsiasi classe di Rails).

Se non si conoscono abbastanza bene Rails e Ruby da poter scrivere un plugin per Discourse, la mia esperienza è che forkare Discourse e intervenire sul core è un approccio “fuori strada”.

Immagino che l’analogia sia questa (scusa per l’idea così semplice):

“Qualcuno trova difficile camminare; quindi decide di correre invece.”

Fammi spiegare, se non ti dispiace:

Prima di iniziare a scrivere applicazioni Rails (niente a che vedere con Discourse) e di provare a scrivere plugin per Discourse, ero un po’ perso; e, credo, ero anche un po’ infastidito da Discourse. È come quando si vuole colpire una pallina da golf per la prima volta: non va dritta e ci vuole molto lavoro per colpirla al centro del fairway. Forkare Discourse è come tirare fuori il driver lungo dal range di pratica prima di saper fare chip e putt con i ferri corti!

Ho preso una pausa dal lavorare su Discourse (molti mesi fa) e ho lavorato per un po’ costruendo effettivamente diverse applicazioni Rails da zero; e solo allora ho iniziato a sviluppare una conoscenza “istintiva” di Rails. Dopo di che, quando ho deciso di modificare Discourse (attualmente sto eseguendo in produzione 6 plugin personalizzati che ho scritto per Discourse), tutto è diventato intuitivo e i plugin che modificavano il core di Ruby sono diventati troppo semplici.

Ruby è molto flessibile. Possiamo sovrascrivere qualsiasi classe, qualsiasi oggetto. Possiamo ridefinire ogni aspetto di Ruby. Con un po’ di esperienza, iniziamo a dire “WOW”, non sapevo che Ruby fosse così flessibile (e potente), e iniziamo a “diventare pericolosi” perché possiamo volare come Superman con Ruby e Rails. Siamo all’inizio del nostro viaggio in Ruby e Rails in quel momento, non alla fine!

Con le conoscenze di Ruby e Rails che ho acquisito nel 2020, sapendo quello che so ora, non forkerei mai Discourse e apporterei modifiche al core di Ruby e Rails come stai proponendo tu, perché i plugin sono semplicemente troppo facili per sovrascrivere e modificare le classi di Ruby, quando si comprendono le basi delle classi di Ruby e le basi della metaprogrammazione.

Credo di voler dire, scusa per essere così diretto, che se qualcuno pensa di dover hackerare il core di Discourse per apportare alcune modifiche minori a Ruby, allora non conosce abbastanza Ruby e Rails; perché se lo conoscesse, non hackererebbe il core e scriverebbe semplicemente un rapido plugin per sovrascrivere le classi e amerebbe il monkey-patching.

D’altra parte, se volessi fare qualcosa di folle e diventare infelice, come sostituire EmberJS di Discourse con React e Ant Design, allora il fork sarebbe l’unica strada da percorrere! Tuttavia, a mio avviso, “Discourse” non è definito dalle “librerie Javascript”. Discourse è definito dalle competenze del team di sviluppo core (le persone) e dalla loro attenzione ai dettagli, dal servizio clienti, dall’approccio di squadra allo sviluppo di codice open source, dalla loro pipeline di funzionalità SPA e da tutto il loro duro lavoro! Sarebbe un po’ pazzo (a mio avviso) buttare via tutto quel potenziale intellettuale solo perché potremmo preferire Ant Design (con React) o VueJS rispetto a Ember.

La stessa cosa è ancora più vera se stiamo solo modificando il core di Discourse qui e là! Sarebbe un po’ “matto” forkarlo per farlo, buttando via le “persone” che sono il “vero” Discourse (non il codice).

Sto parlando solo del mio viaggio personale nel 2020 nell’apprendimento di Ruby e Rails. Ora, le cose stanno diventando facili (le basi) e sono “pericoloso”, LOL. Posso “giocare con il monkey patching su qualsiasi cosa”, il che non è sempre una buona cosa; ed è proprio per questo che servono i plugin di Discourse.

Mantieni il core solido come una roccia e divertiti a “giocare” con Discourse tramite i plugin.

Spero che questo aiuti.

Nota: mentre scrivevo questa risposta, hai scritto:

Questo in un certo senso conferma il mio punto, non credi?

Scrivere un “plugin” in Discourse significa scrivere “codice Ruby” (a un certo livello) e per altri va molto più a fondo (in EmberJS).

Prima di iniziare a scrivere plugin per Discourse, il mio consiglio amichevole, che potrebbe sembrarti privo di valore, è di sviluppare prima alcune applicazioni Ruby on Rails. Impara a muoverti tra Ruby e Rails, almeno le basi; dopo di che, avrai già risposto alla tua stessa domanda qui sopra.

Il percorso più breve per scrivere plugin per Discourse, a mio avviso, è imparare prima Rails.

Spero che questo aiuti!

5 Mi Piace

Ecco un buon punto di partenza:

3 Mi Piace

No, hai assolutamente ragione. Non ho alcuna esperienza con Ruby, quindi non prendo assolutamente nulla in modo personale!

Ho consultato la guida ai plugin e l’ho letta un paio di volte, ma purtroppo la mia ignoranza su Ruby continua a frustrarmi, e non ho la minima idea di come potrei scrivere un plugin che sovrascriva quel piccolo frammento di codice nel file user-guardian per permettere agli utenti anonimi di modificare i propri nomi. :confused:

2 Mi Piace

Ciao @leighno5,

Sì, ti capisco.

Quegli argomenti “HOWTO” sui plugin sono stati scritti da sviluppatori molto talentuosi con oltre un decennio di esperienza nella programmazione in Rails e Ruby (forse anche di più). In effetti, alcuni di loro sono tra i migliori sviluppatori Ruby e JS al mondo.

Sono assolutamente certo, al 100%, che tutti loro abbiano imparato Rails e Ruby molto prima di scrivere il loro primo plugin per Discourse.

In realtà, imparare Rails non è così difficile; ma devi davvero fare il “rito pratico” di costruire alcune applicazioni Rails da zero. Non limitarti a seguire un tutorial su YouTube (che è utile), ma costruisci davvero un’applicazione funzionante in cui devi gestire la configurazione del database, generare i tuoi modelli, creare i tuoi controller, scrivere validazioni per i modelli, creare inizializzatori, moduli helper, eseguire migrazioni (modifiche) al database, lavorare con Ruby incorporato e altro ancora.

È davvero molto divertente ed è la “via più breve” per imparare a scrivere plugin con sicurezza (per quanto riguarda la parte di Rails; personalmente non lavoro molto con Ember, ma amo la parte di Rails)!

Inoltre, devi imparare a usare la console di Rails! La console di Rails è davvero divertente e la uso ogni giorno con piacere!

Oggi, il mio cliente preferito e io stavamo usando AnyDesk e mi ha chiesto: “Possiamo avere questa nuova vista dell’inventario?”. Voleva guardarmi mentre lo facevo tutto. Dopo averlo messo in funzione, alla fine della chiamata mi ha detto: “Hai fatto qualcosa in Rails in 30 minuti che, qualche decennio fa, avrebbe richiesto diverse settimane!!”. Davvero fantastico, @leighno5. Vai avanti!!

Dopo aver imparato Rails, dirai: “WOW”, scrivere plugin per Discourse è abbastanza facile, almeno per la parte di Rails e Ruby!!

Spero ti sia utile.

3 Mi Piace

Guarda il codice #plugin esistente. Ce ne sono assolutamente un sacco ora, quindi ci sono molti esempi. Non saltare la lettura del lavoro precedente in modo da poterlo sfruttare.

Sembra che tu voglia semplicemente sovrascrivere un metodo, il che è un semplice caso di ridefinirlo nel tuo plugin.rb (anche se la migliore pratica è, a mio avviso, separarlo in un file dedicato per modulo, ma non ne vale la pena per un solo metodo!)

5 Mi Piace

A rischio di mostrare ulteriormente la mia ignoranza e di approfittare della gentilezza che mi hai già dimostrato, saresti disposto ad approfondire un po’ questo punto? O, se conosci un altro esempio in cui qualcuno ha sovrascritto un modulo e puoi fornire un link, ne sarei grato. Non sono affatto contrario al “leggi il manuale” (RTFM), ma la mia mancanza di comprensione di come funziona Discourse è frustrante, nonostante tutto il tempo che ho dedicato a esaminare vari tutorial e documenti. E sì, so che domande così basilari fanno sembrare che abbia fatto pochi sforzi, ma ti prometto che non è così!

3 Mi Piace

Ecco un esempio in cui abbiamo definito un metodo in PostGuardian:

Potresti fare qualcosa di simile per UserGuardian utilizzando il nome del metodo esistente, che dovrebbe sovrascriverlo.

Soluzione semplice (per farlo funzionare, anche se non in modo robusto):

Scrivi letteralmente il codice originale del metodo e apporta la tua modifica. Svantaggio: se Discourse modifica il codice, il tuo plugin potrebbe causare problemi all’istanza.

Soluzione avanzata (più robusta):

Per un tocco in più, potresti riuscire a usare super per ereditare il metodo originale, ma non è garantito che funzioni per motivi che non approfondirò qui. Tuttavia, è una buona pratica perché così gli aggiornamenti di quel metodo in Discourse verranno sempre presi in considerazione senza che tu debba modificare il tuo plugin.

Discourse è una piattaforma. Ci vuole tempo per impararla. Procedi passo dopo passo.

6 Mi Piace

È proprio questo che mi preoccupava. Il metodo avanzato menzionato nel paragrafo successivo è trattato nella guida pratica? Esiste un buon esempio semplice del suo utilizzo in un plugin esistente che potrebbe essere usato (copiato) per crearne uno nuovo?

Per ora non preoccuparti del metodo avanzato. Fai semplicemente in modo che funzioni. Puoi approfondire Ruby on Rails in generale altrove nelle guide online. È un po’ fuori dall’ambito specifico di Discourse e di questo forum. Tienilo a mente.

1 Mi Piace

Ok, grazie! Diciamo che mi metto a scrivere un breve plugin. Se ho capito bene, dovrei poi controllare il codice principale ad ogni aggiornamento e riscrivere il plugin se il codice principale rilevante è cambiato. È tutto? Grazie.

1 Mi Piace

È corretto. Controllalo solo occasionalmente e soprattutto se inizia a malfunzionare. Il codice Guardian è un po’ più critico poiché gestisce l’autorizzazione del sito di codifica, quindi tienilo d’occhio.

Un’altra soluzione è aggiungere casi di test (noti anche come specifiche) e configurare un’attività automatizzata per eseguirli… ma diventa complicato!

2 Mi Piace

Un altro compito extra è configurare travis-ci.org per eseguire i test del tuo plugin, in modo da ricevere un avviso se qualcosa si rompe.

5 Mi Piace

Chiaramente non è un compito da sottovalutare. Vorrei modificare i modali di accesso/creazione nuovo account ed eliminare l’immagine di Twitter. Forse quest’ultimo sarebbe un progetto migliore da iniziare. Grazie.

Se qualcuno si imbatte in questo e si è sentito così perso come me, ecco il mio codice, poiché sono riuscito a farlo funzionare come previsto. Non ho modificato alcun file. Ho semplicemente creato un nuovo file plugin.rb e inserito al suo interno quanto segue:

# about: Consente agli utenti in Modalità Anonima di modificare i propri nomi utente
# 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

Questo sovrascrive la classe user_guardian.rb nel core di Discourse per consentire agli utenti di modificare il nome utente e il nome dei propri account anonimi.

Se confronti ciò che ho qui con quanto contenuto in user_guardian.rb nel core di Discourse, puoi notare che c’è un sacco di altro codice con cui non ho dovuto fare nulla, quindi l’ho lasciato com’era. Tutto ciò che mi serviva era modificare quei due metodi can_edit_username e can_edit_name cambiando alcuni valori di ritorno da false a true, e sono riuscito a ottenere ciò che mi serviva.

Certamente ci sono miglioramenti che potrebbero essere apportati, e probabilmente ci sono le migliori pratiche che sono riuscito a cogliere leggendo i post collegati qui e altrove, ma se sei nuovo a Ruby come me e vuoi solo apportare una modifica molto semplice al core, questo è un esempio minimale funzionante di ciò che devi fare.

Molte grazie alle persone in questa discussione per la loro pazienza, il loro incoraggiamento e il loro aiuto! In particolare a @merefield, che in passato mi ha già aiutato con un altro post.

10 Mi Piace

LOL

Sei arrivato molto lontano rispetto all’idea iniziale di fare un fork di tutto Discourse e abbandonare il ramo principale per compiti semplici come questi.

Bravo :slight_smile:

4 Mi Piace

Hai seguito l’intera procedura di Install Discourse on Ubuntu or Debian for Development o hai lavorato direttamente sul tuo sito di produzione sperando nel meglio?