Questo è un argomento che è emerso più volte e si è bloccato (di solito perché lo sviluppatore non richiede effettivamente la chiamata AJAX). Tuttavia, sto sviluppando un plugin che accede a dati non memorizzati nel database di Discourse (bot Discord autonomo) e sto cercando di utilizzare tali dati per decorare i post.
export default Component.extend({
init() {
this._super(...arguments);
var self = this;
const store = getOwner(this).lookup("service:store");
let positions = [];
store
.findAll("position", {
...args,
})
.then((data) => {
for (const [key, position] of Object.entries(data.content)) {
positions.pushObject(EmberObject.create({ ...position }));
}
});
withPluginApi("1.4.0", (api) => {
api.reopenWidget("post", {
html(attrs) {
let position = positions.filter(
(position) => position.user.id == attrs.user.id
);
if (position.length > 0) {
attrs.cooked = "Has Position";
}
return this.attach("post-article", attrs);
},
});
});
},
});
Ora ho provato diverse varianti di questo codice, inclusa la chiamata alla funzione api nella porzione .then della query dello store e così via, e tutte finiscono allo stesso modo, ovvero non rendono le modifiche ai post finché non si scorre.
Tutti questi tentativi sono stati fatti a tarda notte, quindi è molto probabile che mi stia sfuggendo qualcosa di super ovvio, tuttavia, qualsiasi aiuto sarebbe molto apprezzato.
Dipende da cosa stai cercando di fare, suppongo, ma perché non usare l’API Ruby ufficiale di Discord per inserire i dati nel database di Discourse, serializzarli sul client e poi usarli nel widget?
Sembrava una complessità non necessaria quando l’API delle applicazioni principali è sufficiente per la maggior parte delle cose, ma potrei fraintendere l’implementazione poiché, a dire il vero, dovrò studiare un po’ di più il lato Ruby di Discourse.
Anche se non riesco a far funzionare la decorazione dei post, probabilmente dovrò seguire quella strada.
Tornando indietro per ringraziare @merefield, ho approfondito la serializzazione e sono riuscito a completare l’attività effettuando la chiamata API nel serializzatore invece di richiederla da JS come stavo facendo.
Sono sicuro che ci siano una miriade di ragioni per cui questo non è consigliato, ma funziona per me, quindi lo sto portando avanti. Per coloro che trovano questo in futuro, è possibile inserire dati in un serializzatore con il seguente codice:
add_to_serializer(:topic_view, :data_name) do
JSON.parse(Net::HTTP.get(URI('https://yourwebsite.com?topic_id=' + object.topic.id.to_s)))
end
Il che ti consente quindi di accedere ai dati all’interno di una chiamata a reopenWidget. Nel mio caso, sto aggiungendo i dati pertinenti all’argomento al serializzatore topic_view e accedendovi mentre modifico il post in questo modo:
api.reopenWidget("post", {
html(attrs) {
let data_name = this.model.topic.data_name;
// Fai cose con i dati
return this.attach("post-article", attrs);
},
});
Come ho detto prima, probabilmente ci sono un sacco di ragioni per cui questo non è il modo giusto di procedere, ma sta funzionando per il mio caso d’uso con un impatto minimo sui tempi di caricamento.
Hmmm… non sono sicuro che sia architettonicamente valido. Sebbene sia fantastico che tu stia esplorando una soluzione back-end (le chiamate al server remoto dovrebbero quasi sempre avvenire tra processi sul back-end, specialmente quando sono coinvolti autenticazione e autorizzazione), i dati dovrebbero probabilmente caricarsi in modo asincrono e il serializzatore non dovrebbe fare affidamento su una chiamata remota per concludere. Almeno dovresti racchiudere quella chiamata in una cache?
Vedi come va, ma presta molta attenzione ai tempi di caricamento della pagina prima e dopo quella modifica, potresti introdurre un ritardo significativo.
In pratica, aggiunge tra 10 e 50 ms per caricamento, se non meno. La connessione ha una latenza bassissima poiché entrambe le macchine si trovano nello stesso data center. Infatti, il metodo che sto usando per recuperare i dati nei componenti carica le pagine marginalmente più velocemente rispetto al rendering delle pagine statiche di Discourse (differenza di circa 100 ms) e questo include un’operazione sul database che utilizza gli ID di Discord per aggiungere dati utente alle risposte API prima che vengano inoltrate al client. (Ruby richiede dati dall’applicazione esterna → Analizza JSON → Ciclo each della query DB per aggiungere dati alla risposta → Genera JSON e restituisce al client frontend). È comprensibile considerando quanto è vasto il codebase, ma c’è sicuramente un overhead interno che lascia spazio a queste richieste, tradizionalmente considerate “costose”, per passare completamente inosservate. Detto questo, stiamo parlando della velocità della luce e del suono qui, che per l’utente finale è ancora incredibilmente veloce poiché Discourse è una piattaforma fantastica.
Una cache sarebbe un’ottima aggiunta e ci darò un’occhiata, sono molto nuovo a Ruby, quindi aggiornerò man mano che imparerò di più sulle funzioni disponibili. Aggiornerò questo man mano che andrò avanti perché penso che una sorta di metodo per questo, sebbene al momento sia un po’ un “hack”, potrebbe essere potenzialmente molto vantaggioso per lo sviluppo di plugin. Per le persone con applicazioni esistenti, la possibilità di utilizzare l’API che conoscono per inserire i dati di cui hanno bisogno dove ne hanno bisogno in modo efficiente, senza dover creare sistemi per sincronizzare i dati tra il loro database e Discourse o armeggiare con modelli aggiuntivi o migrazioni del database, riduce drasticamente i tempi di sviluppo e mantiene gli autori dei plugin in alcune delle aree meglio documentate dell’applicazione (cioè l’API dei plugin).
Apprezzo molto l’intuizione, sono decisamente entusiasta di continuare a imparare di più su questa piattaforma e spero di contribuire in futuro.