Ho deciso di creare il plugin. Il componente del modulo stesso viene renderizzato correttamente tramite api.renderInOutlet. Tuttavia, i dati non vengono salvati sul backend nella tabella personalizzata.
Configurazione Frontend:
Sto usando api.renderInOutlet("composer-fields", MyOutletConnectorComponent) per renderizzare un componente GJS (MyOutletConnectorComponent) quando viene creato un nuovo argomento in una categoria designata.
Questo MyOutletConnectorComponent renderizza quindi il mio componente modulo principale GJS (MyMarketFormComponenent).
All’interno di MyMarketFormComponenent, l’input dell’utente aggiorna un oggetto JavaScript che viene quindi impostato come proprietà di livello superiore sul composerModel fornito dagli argomenti dell’outlet. Ad esempio:
Nel mio inizializzatore del plugin (tecenc-market-composer.js), sto usando api.serializeOnCreate("market_listing_data", "market_listing_data"); per tentare di passare questi dati al backend. Uso anche api.serializeToDraft("market_listing_data", "market_listing_data");.
Problema Backend:
Nel mio plugin.rb, all’interno dell’handler DiscourseEvent.on(:topic_created) do |topic, opts, user| ... end:
Verifico se l’argomento è nella categoria corretta (questo funziona).
Quindi provo ad accedere ai dati serializzati usando market_data = opts[:market_listing_data] (o opts["market_listing_data"]).
Il problema è che opts[:market_listing_data] è costantemente nil.
Il logging di opts.keys conferma che la mia chiave market_listing_data non è presente al livello superiore dell’hash opts. L’hash opts stesso contiene chiavi standard come :raw, :title, :category, :archetype, ecc.
Il mio snippet plugin.rb per l’evento:
# plugin.rb
# ...
module ::TecencMarket
SERIALIZED_DATA_KEY = "market_listing_data".freeze
end
# ...
after_initialize do
# ...
DiscourseEvent.on(:topic_created) do |topic, opts, user|
# ... (logica di controllo della categoria) ...
# È qui che market_data è nil
market_data = opts[TecencMarket::SERIALIZED_DATA_KEY.to_sym]
Rails.logger.info "[MyPlugin] Opts keys: #{opts.keys.inspect}"
Rails.logger.info "[MyPlugin] market_data from opts: #{market_data.inspect}"
if market_data.present? && market_data.is_a?(Hash)
# ... elabora e salva i dati nella tabella personalizzata ...
else
Rails.logger.warn "[MyPlugin] Market data not found in opts as expected."
end
end
# ...
end
Domanda:
Qual è il modo corretto e più affidabile per garantire che un oggetto JavaScript impostato come proprietà di livello superiore sul composerModel (ad esempio, composerModel.set("my_plugin_data_key", { ... });) utilizzando componenti GJS venga correttamente serializzato da api.serializeOnCreate e reso disponibile nell’hash opts dell’evento :topic_created sul backend?
api.serializeOnCreate("my_key", "my_key") è previsto che funzioni per chiavi arbitrarie di livello superiore impostate sul composerModel da un contesto GJS, o la serializzazione tramite custom_fields (ad esempio, impostando composerModel.custom_fields.my_plugin_key = {...} e utilizzando api.serializeOnCreate("custom_fields.my_plugin_key")) è l’unico approccio robusto/raccomandato per questo tipo di trasferimento dati per nuovi argomenti?
Ci sono considerazioni specifiche o errori comuni quando si utilizza api.serializeOnCreate con dati gestiti da componenti GJS che potrebbero causare la mancata inclusione dei dati nell’hash opts?
Ho confermato che il modulo frontend sta raccogliendo correttamente i dati e li sta impostando sulla proprietà composerModel.market_listing_data. Il problema sembra essere puramente nell’ottenere questi dati serializzati e passati all’evento backend.
Qualsiasi guida o esempio del modello raccomandato per questo nel moderno Discourse sarebbe molto apprezzato!
In seguito al mio problema precedente riguardo al fatto che i dati non raggiungessero l’hash opts, ho modificato la mia strategia per utilizzare il percorso raccomandato custom_fields per serializzare i dati dal modulo del plugin del mio compositore.
Approccio Attuale:
Inizializzatore Frontend:
Sto cercando di assicurarmi che composerModel.custom_fields e composerModel.custom_fields["tecenc_market_data"] (la chiave dei dati del mio plugin) siano inizializzati come oggetti. La mia ultima prova consiste nell’usare api.modifyClass("model:composer", ...) per aggiungere la logica di inizializzazione a init() e clearState():
Successivamente utilizzo api.serializeOnCreate('custom_fields.tecenc_market_data'); e api.serializeToDraft('custom_fields.tecenc_market_data');.
Il mio componente GJS del modulo aggiorna composerModel.custom_fields.tecenc_market_data.my_field = value; (impostando un nuovo oggetto custom_fields per la reattività).
Backend plugin.rb:
Viene chiamato Topic.register_custom_field_type("tecenc_market_data", :json).
L’handler di evento topic_created si aspetta di leggere i dati da topic.custom_fields["tecenc_market_data"].
Nuovo Errore Blocante:
Nonostante questi tentativi di inizializzare custom_fields sul composerModel, sto ora incontrando sistematicamente il seguente errore JavaScript quando provo ad aprire il composer per un nuovo argomento (cliccando sul pulsante “Create Topic”):
Uncaught (in promise) Error: Property set failed: object in path "custom_fields" could not be found.
Ember 3
open composer.js:1010
open composer.js:1009
_setModel composer.js:1451
open composer.js:1401
openNewTopic composer.js:1410
createTopic list.js:167
clickCreateTopicButton d-navigation.gjs:224
_triggerAction d-button.gjs:138
Ember 11
_triggerAction d-button.gjs:135
click d-button.gjs:93
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:94366
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:94040
Ember 26 property_set-BapAkp3X.js:79:10
Questo errore indica che this.model.custom_fields (sul composerModel) è undefined o null quando il codice core di Discourse in composer.js:1010 (all’interno del metodo open, chiamato da openNewTopic) tenta di impostare una proprietà nidificata su di esso. Questo accade prima che il modulo del mio plugin possa essere nemmeno renderizzato.
Domande:
Dato che il modello Composer core dovrebbe inizializzare custom_fields: {}, perché composerModel.custom_fields potrebbe comunque essere undefined a composer.js:1010 durante la sequenza openNewTopic in questa versione di Discourse?
L’approccio api.modifyClass("model:composer", ...) in un initializer è il modo corretto/più efficace per garantire che custom_fields (e le chiavi nested del plugin al suo interno) siano inizializzati come oggetti abbastanza presto da prevenire questo errore core? Se no, qual è il pattern raccomandato?
Potrebbe esserci un problema di timing in cui i passaggi di inizializzazione del composer core vengono eseguiti e si aspettano che custom_fields sia disponibile prima che gli initializer del plugin, usando api.modifyClass, abbiano effettivamente effetto sulla prototipo o sulle istanze del modello Composer?
Qualsiasi insight su questo errore “Property set failed” nel core del composer e sulle migliori pratiche per i plugin per interagire in modo sicuro con composerModel.custom_fields durante l’inizializzazione sarebbe estremamente utile.
Sto salvando i dati in una tabella di database personalizzata.
addToSerializer serve per spostare i dati dal server al client, vero?
Il mio problema è spostare i dati dal client al server in modo da poterli salvare. Quindi sto usando serializeOnCreate. Ma il problema è che i dati non fluiscono nell’hash opts. Quindi, attualmente, la risposta è no, i dati personalizzati non stanno entrando nell’hash opts come previsto. Non stanno arrivando a Rails.
Ho esaminato questo plugin educativo ma non sono riuscito a farlo funzionare per 6 campi personalizzati.