إضافات Discourse وإعدادات config/initializers لـ Rails 6

مرحبًا أيها الخبراء في إضافات Discourse،

سؤال سريع بخصوص إضافات Discourse وتهيئات Rails.

إذا كانت إضافة Discourse تحتوي على مجلد يُسمى “config” ومجلد فرعي تحت “config” يُسمى “initializers”، فهل تقوم تطبيق Rails الخاص بـ Discourse بقراءة جميع ملفات التهيئة الخاصة بالإضافة الموجودة تحت مجلد “initializers” تمامًا كما يفعل Rails 6؟

السبب في سؤالي هو أنني بصدد كتابة تطبيق Rails 6 من نوع “المكتب الخلفي” (Rails فقط، بدون EmberJS أو أي إطار عمل JavaScript آخر) من الصفر لعميل، ولدي مجلد تحت initializers على النحو التالي:

./config/initializers/client/

… وجميع ملفات التهيئة الفريدة الخاصة بالعميل موجودة في المجلد الفرعي “client”.

Rails 6 يقرأ جميع الملفات الموجودة تحت مجلد التهيئة القياسي (حتى المجلدات الفرعية)، لذا تساءلتُ عما إذا كانت إضافات Discourse، مع بنية مجلدات مماثلة للتهيئات، ستعمل مثل Rails 6 وتقرأ جميع ملفات التهيئة في الإضافة على النحو التالي:

./plugins/my_plugin/config/initializers/myclient/
      client_initializer1.rb
      client_initializer2.rb
      client_initializer3.rb

… دون تسجيل هذه الأصول في ملف plugin.rb؟

شكرًا لكم!

ملاحظة: لقد تفحصتُ حوالي 10 إضافات لـ Discourse على GitHub، ولم يكن لأي منها ملفات تهيئة تحت مجلد config. وهذا هو السبب في أنني قررتُ طرح السؤال (وبيئة تطوير Rails الخاصة بي غير مُعدة حاليًا لـ Discourse، فهي مُعدة بالكامل للعميل).

إعجابَين (2)

أود أيضًا أن أعرف الفرق بين إضافة Discourse ومحرك Rails العادي. لقد كنت أبحث فقط في الكود المصدري لكنني لم أستوعب الكثير.

بعد التصفح السريع في هذه الصفحة Ruby on Rails Guides: Configuring Rails Applications
أعتقد أن ملف plugin.rb هو إلى حد كبير نفس الشيء. فمعظم الإضافات التي حجمها لائق تستخدمه كنقطة دخول للمنطق بدلاً من أن يكون هو المنطق نفسه.

نعم، لقد قرأت دليل Rails هذا كثيرًا مؤخرًا. بشكل عام، أنا “مُرضٍ” من طريقة عمل إعدادات Rails 6 (ما زلت أتعلم، لكنني أصبح أكثر راحة كل يوم).

أنا أتساءل فقط عما إذا كان بإمكاننا استخدام نفس البنية في إضافة Discourse (للمُهيئات)، وهل سيقوم Rails بقراءة المُهيئات في المجلدات الفرعية كما يفعل في Rails 6؛ أم أننا مضطرون لتسجيل مجلد مُهيئات الإضافة كـ “أصل” إعدادات (لعدم وجود كلمة أفضل) في ملف plugin.rb.

كنت أقرأ عن إضافات Rails أمس وقارنتها أيضًا قليلاً.

حسب علمي، لا يقرأ Discourse أي ملف Ruby سوى plugin.rb. لكنه يقرأ ملفات JS وملفات التكوين. يجب تضمين جميع ملفات Ruby باستخدام require في plugin.rb.

3 إعجابات

أعتقد ذلك أيضًا.

يمكنك تحميل أي ملفات Ruby إضافية تحتاجها من داخل plugin.rb.

إليك مثال من إضافة Follow:

إعجاب واحد (1)

هذا الانطباع الذي توصلت إليه أيضًا بعد قراءة عدد من إضافات Discourse على GitHub.

يبدو أن Discourse يقرأ ملف plugin.rb فقط، ويجب علينا تحميل جميع ملفات Ruby الأخرى التي قد نحتاجها، مثل ملفات التهيئة (initializers)، داخل plugin.rb.

ومع ذلك، كنت أتمنى أن أكون مخطئًا وأن يكون هناك تكامل “أعمق” بين إضافات Discourse و Rails؛ لأنني اعتدت على روعة Rails 6.

شكرًا لك على التأكيد أيضًا.

إعجاب واحد (1)

أعتقد أنه يجب أن تكون هناك طريقة لطلب كود التهيئة في plugin.rb أيضًا.
هل جربت هذا في plugin.rb

Rails.application.config.before_initialize do
  # كود التهيئة يوضع هنا
end

نعم، لا توجد مشكلة في استدعاء وتحميل مهيئات التهيئة في ملف plugin.rb.

كان سبب سؤالي هو أنني أكتب حاليًا تطبيقًا كبيرًا نسبيًا مبنيًا على Rails 6 لأحد الشركات، لتحويل نصوصهم القديمة الخاصة بالمكتب الخلفي (التي تمتد على عدة عقود) إلى تطبيق Rails. ولإضافة مهيئات التهيئة، أنشأت مجرد مجلد فرعي تحت config/initializers (في Rails)، وتتم إدراج جميع ملفات المهيئات الخاصة بي بشكل أنيق دون الحاجة إلى كتابة أي كود لإدراج هذه الملفات في Rails.

شكرًا لجميع ردودكم. نقدر ذلك كثيرًا!

إعجاب واحد (1)

نعم، سأحب جداً لو تم نقل مزايا Rails إلى إضافات Discourse. من بين المفضلة لدي شخصياً، القدرة على إعادة تحميل ملفات Ruby مباشرة دون إعادة تشغيل الخادم.

إعجاب واحد (1)

هذا هو الغرض من reloadable_patch. إذا قمت بتغليف تغييرات فئة Ruby داخل reloadable_patch، فستتم إعادة تحميلها مباشرة!

إعجاب واحد (1)

هل يمكنني تغليف ملف plugin.rb بالكامل بداخله لأغراض التطوير؟ وبشكل أكثر جدية، إلى أي مدى يمكننا الذهاب باستخدامه؟

أيضًا، هل يتطلب إضافة ملفات جديدة أو تغيير أي ملفات yml إعادة تشغيل الخادم؟

إعجابَين (2)

لا يجب أن تضطر إلى استخدام reloadable_patch لكل شيء. العديد من الطرق المحددة في instance.rb لتسهيل تطوير الإضافات تستخدم reloadable_patch داخليًا، مثل add_to_serializer.

من الناحية المثالية، يجب أن تكون واجهة برمجة تطبيقات الإضافة لدينا جيدة لدرجة أنك لن تضطر إلى القيام بكمية هائلة من استخدام reloadable_patch.

نعم، هذا صحيح. أتساءل عما إذا كان يمكن فعل أي شيء بشأن تغييرات ملفات yml؛ فهذا الأمر يزعجني شخصيًا.

3 إعجابات

صحيح ذلك. لم أكن أعرف أن reloadable_patch مخصص لدعم إعادة التحميل المباشر. يمكنني التفكير في العديد من حالات الاستخدام بخلاف تلك التي يستخدمها Discourse بالفعل، أي:

reloadable_patch do
 require 'x/y/z'
end

أو التصحيحات التعديلية (monkey patches).

إعجاب واحد (1)

أعتقد أن إزالة أو إضافة مثل هذه الدالة ستظل مشكلة لأن reloadable_patch تُستدعى داخل الدالة.

على أي حال، هذا يساعد كثيرًا.

إعجاب واحد (1)

بدأت في استكشاف إعادة التحميل المباشر للتغييرات في ملفات YAML، وهو ما يعمل بالفعل. قد تؤدي الإضافات إلى تعطيل هذه الميزة إذا لم تستخدم reloadable_patch بشكل صحيح، ولكن بمجرد أن تتمكن جميع الإضافات الخاصة بك من إعادة التحميل بأمان، ستعمل التغييرات في ملفات YAML أيضًا.

4 إعجابات

سيكون ذلك مفيدًا للغاية لو أمكنك وصف الخطوات الدقيقة لاستخدام التصحيح القابل لإعادة التحميل.

إليك ما حاولت فعله دون نجاح كبير (أنا بالتأكيد أفتقد شيئًا ما):

after_initialize do
    add_to_serializer(:topic_view, :check, false) do
        puts 'nocheck'
    end
end

بمجرد بدء تشغيل الخادم، وعندما أغير nocheck إلى check، لا يزال يطبع nocheck بعد إعادة تحميل مسار الموضوع.

after_initialize do
    reloadable_patch do |plugin|
        puts 'nocheck'
    end
end

لا يزال دون جدوى عند إعادة تحميل أي صفحة بعد تغيير السلسلة تحت puts.

أظن أنني أضللّتك في المنشورات أعلاه. reloadable_patch مفيد لتطوير Discourse، لكن @david شرح استخدامه بشكل ممتاز:


أي شيء داخل كتلة after_initialize في ملف plugin.rb يتم تحميله فقط أثناء بدء تشغيل التطبيق، وليس عند إعادة التحميل اللاحقة.

لذا، بافتراض أنك تريد إضافة شيء ما إلى مُسلسل المستخدم (user serializer). السلوك الطبيعي يكون كالتالي:

أثناء بدء التشغيل:

  • يقوم Discourse بتحميل user_serializer.rb
  • يقوم Discourse بتحميل plugin.rb، الذي يحتوي على تجاوز لـ user_serializer

أثناء إعادة التحميل:

  • يقوم Discourse بإعادة تحميل user_serializer.rb
  • (لا يتم إعادة تحميل تصحيح plugin.rb، ويتم فقدان تجاوز الإضافة)

مع نظام reloadable_patch الخاص بنا:

أثناء بدء التشغيل:

  • يقوم Discourse بتحميل user_serializer.rb
  • يقوم Discourse بتحميل plugin.rb ويسجل reloadable_patch الخاص بـ user_serializer
  • يتم تنفيذ التصحيحات القابلة لإعادة التحميل

أثناء إعادة التحميل:

  • يقوم Discourse بإعادة تحميل user_serializer.rb
  • يتم تنفيذ التصحيحات القابلة لإعادة التحميل
  • (يا له من رائع، لا يزال تجاوز الإضافة يعمل)
6 إعجابات

هذا يصف خاصية أساسية في Rails، وهي غير ذات صلة مباشرة بـ Discourse.

في Rails، يتم تحميل جميع المهيئات (initializers) فقط عند بدء تشغيل Rails، لذا فإن أي إضافة (plugin) تنفذ كودًا بناءً على المهيئات، مثل “after_initializer”، ستنفذ فقط عند بدء تشغيل Rails أو إعادة تشغيله (أرجو تصحيحي إذا كنت مخطئًا).

السبب في معرفتي بهذا هو أنني أقوم حاليًا ببناء تطبيق Rails لعميل، وقد كتبت العديد من المهيئات لمهام مختلفة (قيم منطقية، مصفوفات ثابتة، إلخ). في كل حالة، إذا قمنا بتغيير أي كود في مهيئ Rails، فإننا نحتاج إلى إعادة تشغيل Rails (“Control c، ثم rails s في وضع التطوير”) لتطبيق القيم الجديدة في المهيئات داخل تطبيق Rails.

أرجو تصحيحي إذا كنت مخطئًا! شكرًا لك.

في بعض الأحيان، أعتقد أن هذا قد يكون مربكًا قليلاً لبعض مطوري إضافات Discourse، خاصة أولئك الذين يعملون بشكل أساسي على إضافات Discourse وليس مع تطبيقات Rails بشكل عام، عندما نكتب “Discourse يفعل هذا” أو “Discourse يفعل ذلك” بينما ما نصفه حقًا هو وظيفة أو خاصية أساسية في Rails وليست بالضرورة مرتبطة بـ Discourse بحد ذاتها.

Rails 6 يقرأ جميع الملفات الموجودة في مجلد config/initializers (وكل المجلدات الفرعية داخل config/initializers) فقط عند بدء تشغيل Rails. وبالمثل (لست متأكدًا بنسبة 100% بشأن الإضافات)، فإن إضافة Discourse التي تحتوي على كود يعتمد على after_initialize سيتم تحميلها بواسطة تطبيق Rails فقط عند بدء تشغيل Rails أو إعادة تشغيله، لأن هذه خاصية أساسية لعملية بدء تشغيل Rails.

تخميني هو أن الجميع هنا يعرفون هذا بالفعل من يعملون على Rails. أنا فقط بدأت أعرف هذه التفاصيل (وأشعر أن لدي طريقًا طويلًا لأصبح خبيرًا)؛ لأنني أعمل حاليًا على تطبيق Rails يوميًا (في هذه الأيام)، والذي بالمناسبة، أتمنى الآن أن أبدأ العمل مع Rails قبل عقد من الزمان، لأنه قادمًا من خلفية تطوير LAMP، أجد Rails أفضل بكثير (سهلة وممتعة للعمل معها).

أصبحت معجبًا كبيرًا بـ Rails هذا العام، وأنا ممتن جدًا لـ Discourse لكونها نقطة البداية في هذا المسار.

مرة أخرى، أرجو تصحيحي إذا كنت مخطئًا! شكرًا لك. أنا أحاول أن أصبح أكثر خبرة في Rails.

6 إعجابات

نعم! هذا صحيح تمامًا مثل فهمك للمُهيئات في Rails.

أنا أيضًا من المعجبين الكبار بـ Rails :slight_smile:

7 إعجابات