قررت إنشاء المكون الإضافي. يتم عرض مكون النموذج نفسه بشكل صحيح عبر api.renderInOutlet. ومع ذلك، لا يتم حفظ البيانات في الخلفية في الجدول المخصص.
إعداد الواجهة الأمامية:
أستخدم api.renderInOutlet("composer-fields", MyOutletConnectorComponent) لعرض مكون GJS (MyOutletConnectorComponent) عند إنشاء موضوع جديد في فئة معينة.
يقوم MyOutletConnectorComponent بعد ذلك بعرض مكون النموذج الرئيسي GJS (MyMarketFormComponenent).
داخل MyMarketFormComponenent، يقوم إدخال المستخدم بتحديث كائن JavaScript الذي يتم تعيينه بعد ذلك كخاصية على المستوى الأعلى لـ composerModel المقدمة من وسائط المخرج. على سبيل المثال:
// داخل إجراء MyMarketFormComponenent
const currentData = this.args.composerModel.get("market_listing_data") || {};
const updatedData = { ...currentData, [fieldKey]: newValue };
this.args.composerModel.set("market_listing_data", updatedData);
في مُهيئ المكون الإضافي الخاص بي (tecenc-market-composer.js)، أستخدم api.serializeOnCreate("market_listing_data", "market_listing_data"); لمحاولة تمرير هذه البيانات إلى الخلفية. أستخدم أيضًا api.serializeToDraft("market_listing_data", "market_listing_data");.
مشكلة الخلفية:
في plugin.rb الخاص بي، ضمن معالج DiscourseEvent.on(:topic_created) do |topic, opts, user| ... end:
أتحقق مما إذا كان الموضوع في الفئة الصحيحة (هذا يعمل).
ثم أحاول الوصول إلى البيانات المسلسلة باستخدام market_data = opts[:market_listing_data] (أو opts["market_listing_data"]).
المشكلة هي أن opts[:market_listing_data] هو دائمًا nil.
يؤكد تسجيل opts.keys أن مفتاح market_listing_data الخاص بي غير موجود على المستوى الأعلى من جدول opts. يحتوي جدول opts نفسه على مفاتيح قياسية مثل :raw و :title و :category و :archetype وما إلى ذلك.
مقتطف plugin.rb الخاص بي للحدث:
# plugin.rb
# ...
module ::TecencMarket
SERIALIZED_DATA_KEY = "market_listing_data".freeze
end
# ...
after_initialize do
# ...
DiscourseEvent.on(:topic_created) do |topic, opts, user|
# ... (منطق التحقق من الفئة) ...
# هذا هو المكان الذي يكون فيه market_data فارغًا
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)
# ... معالجة وحفظ البيانات في جدول مخصص ...
else
Rails.logger.logger.warn "[MyPlugin] Market data not found in opts as expected."
end
end
# ...
end
سؤال:
ما هي الطريقة الصحيحة والأكثر موثوقية لضمان أن كائن JavaScript المعين كخاصية على المستوى الأعلى لـ composerModel (مثل composerModel.set("my_plugin_data_key", { ... });) باستخدام مكونات GJS يتم تسلسله بشكل صحيح بواسطة api.serializeOnCreate ويصبح متاحًا في جدول opts لحدث :topic_created في الخلفية؟
هل من المتوقع أن تعمل api.serializeOnCreate("my_key", "my_key") للمفاتيح العشوائية على المستوى الأعلى المعينة لـ composerModel من سياق GJS، أم أن التسلسل عبر custom_fields (مثل تعيين composerModel.custom_fields.my_plugin_key = {...} واستخدام api.serializeOnCreate("custom_fields.my_plugin_key")) هو النهج الوحيد القوي/الموصى به لهذا النوع من نقل البيانات للمواضيع الجديدة؟
هل هناك أي اعتبارات خاصة أو عيوب شائعة عند استخدام api.serializeOnCreate مع البيانات التي تديرها مكونات GJS والتي قد تتسبب في عدم تضمين البيانات في جدول opts؟
لقد أكدت أن نموذج الواجهة الأمامية يجمع البيانات بشكل صحيح ويعينها على خاصية composerModel.market_listing_data. يبدو أن المشكلة تكمن فقط في تسلسل هذه البيانات وتمريرها إلى حدث الخلفية.
أي توجيه أو أمثلة للنمط الموصى به لهذا في Discourse الحديث سيكون موضع تقدير كبير!
متابعًا لمشكلتي السابقة بخصوص عدم وصول البيانات إلى مؤشر opts، قمت بتحويل استراتيجيتي لاستخدام مسار custom_fields الموصى به لتسلسل البيانات من نموذج الملحق الخاص بي.
النهج الحالي:
مُهيئ الواجهة الأمامية:
أحاول التأكد من أن composerModel.custom_fields و composerModel.custom_fields["tecenc_market_data"] (مفتاح بيانات الملحق الخاص بي) مهيأين ككائنات. آخر محاولة لي تتضمن استخدام api.modifyClass("model:composer", ...) لإضافة منطق التهيئة إلى init() و clearState():
// في مهيئ الملحق الخاص بي (tecenc-market-composer.js)
api.modifyClass("model:composer", {
pluginId: "tecencMarketInitCustomFieldsOnComposer",
init() {
this._super(...arguments);
if (!this.custom_fields || typeof this.custom_fields !== 'object') {
this.custom_fields = {};
}
if (!this.custom_fields["tecenc_market_data"] || typeof this.custom_fields["tecenc_market_data"] !== 'object') {
this.custom_fields["tecenc_market_data"] = {};
}
},
clearState() {
this._super(...arguments);
if (!this.custom_fields || typeof this.custom_fields !== 'object') {
this.set("custom_fields", {});
}
let cf = this.get("custom_fields");
if (!cf["tecenc_market_data"] || typeof cf["tecenc_market_data"] !== 'object') {
const newCustomFields = { ...cf };
newCustomFields["tecenc_market_data"] = {};
this.set("custom_fields", newCustomFields);
}
}
});
ثم أستخدم api.serializeOnCreate('custom_fields.tecenc_market_data'); و api.serializeToDraft('custom_fields.tecenc_market_data');.
يقوم مكون نموذج GJS الخاص بي بتحديث composerModel.custom_fields.tecenc_market_data.my_field = القيمة; (عن طريق تعيين كائن custom_fields جديد من أجل التفاعل).
ملف plugin.rb الخاص بالخادم:
تم استدعاء Topic.register_custom_field_type("tecenc_market_data", :json).
ممعالجة حدث topic_created تتوقع قراءة البيانات من topic.custom_fields["tecenc_market_data"].
الخطأ الجديد المانع:
رغم هذه المحاولات لتهيئة custom_fields على composerModel، أواجه حاليًا الخطأ التالي في JavaScript عند محاولة فتح الملحق لموضوع جديد (بالنقر على زر “إنشاء موضوع”):
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
```تشيرهذه الخطأ إلى أن `this.model.custom_fields` (على `composerModel`) غير معرف أو هو `null` عندما يحاول رمز Discourse الأساسي عند `composer.js:1010` (داخل الدالة `open`، التي تُدعى بواسطة `openNewTopic`) تعيين خاصية متداخلة عليه. يحدث هذا *قبل* أن يتم عرض نموذج النموذج الخاص بي حتى.
**أسئلة:**
1. مع العلم أن النموذج `Composer` الأساسي ينبغي أن يُطيل `custom_fields: {}`، لماذا قد يكون `composerModel.custom_fields` لا يزال غير معرف عند `composer.js:1010` خلال تسلسل `openNewTopic` في إصدار Discourse هذا؟
2. هل نهج `api.modifyClass("model:composer", ...)` في مثيل المهيئ هو الطريقة الصحيحة/الأكثر فعالية لضمان تهيئة `custom_fields` (والمفاتيح الفرعية الإضافية الخاصة بالإضافات بداخلها) ككائنات في وقت مبكر بما يكفي لمنع هذا الخطأ الأساسي؟ إذا لم يكن كذلك، فما هو النمط الموصى به؟
3. هل من المحتمل وجود مشكلة توقيت حيث أن الخطوات الأساسية لتهيئة النموذج المختلط قد تعمل وتتوقع وجود `custom_fields` قبل أن يكون مهيئات الإضافة التي تستخدم `api.modifyClass` قد تدخلت بالكامل على نموذج `Composer` أو التماثيل الخاصة به؟
أي رؤى حول هذا الخطأ "Property set failed" في النواة الخاصة بالمُعدّ غير معروفة في composer وأفضل الممارسات التي ينبغي على الإضافات اتباعها لالتفاعل بأمان مع `composerModel.custom_fields` أثناء التهيئة ستكون مفيدة للغاية.
شكرًا لوقتك!
addToSerializer مخصص لنقل البيانات من الخادم إلى العميل، أليس كذلك؟
مشكلتي هي نقل البيانات من العميل إلى الخادم حتى أتمكن من حفظها. لذلك، أستخدم serializeOnCreate. لكن المشكلة هي أن البيانات لا تتدفق إلى الـ opts hash. لذلك، حاليًا، الإجابة هي لا، البيانات المخصصة لا تصل إلى الـ opts hash كما هو متوقع. إنها لا تصل إلى rails.
لقد نظرت في هذا المكون التعليمي ولكني غير قادر على جعله يعمل لـ 6 حقول مخصصة.