العديد من الإضافات تتضمن تعريفات فئات كثيرة داخل plugin.rb، أو تستخدم require_relative لتحميل ملفات روبي. هذا يعمل، ولكنه يأتي مع بعض العيوب:
- لا يتم إعادة تحميل التغييرات تلقائيًا أثناء التطوير. أي تغييرات تتطلب إعادة تشغيل كاملة للخادم
- الحصول على استدعاءات
requireبالترتيب الصحيح يمكن أن يكون مؤلمًا - إذا تم استدعاؤها خارج كتلة
after_initialize، فقد لا تكون الفئات/الوحدات الأخرى التي يتم تحميلها تلقائيًا متاحة
هناك حل! يمكن للإضافات الاعتماد على نظام التحميل التلقائي القياسي في Rails. بالنسبة للإضافات الجديدة، كل ما تحتاجه محدد في plugin-skeleton. يصف هذا الموضوع كيفية تكييف إضافة موجودة وتوسيع التكوين.
1. تعريف وحدة و Rails::Engine للإضافة الخاصة بك
في plugin.rb، قم بتعريف وحدة للإضافة الخاصة بك باسم فريد PLUGIN_NAME، وأضف سطر require_relative لتحميل ملف المحرك الذي سنقوم بإنشائه.
# name: my-plugin-name
# ...
module ::MyPluginModule
PLUGIN_NAME = "my-plugin-name"
end
require_relative "lib/my_plugin_module/engine"
الآن قم بإنشاء {plugin}/lib/my_plugin_module/engine.rb:
module ::MyPluginModule
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MyPluginModule
end
end
أمور مهمة يجب ملاحظتها:
-
في
plugin.rb، يجب عليك تضمين::قبل اسم الوحدة الخاصة بك لتعريفها في مساحة الاسم الجذر (وإلا، فسيتم تعريفها تحتPlugin::Instance) -
يجب أن يكون
require_relative "lib/.../engine"في جذر ملفplugin.rb، وليس داخل كتلةafter_initialize -
وضع المحرك في ملفه الخاص تحت
lib/أمر مهم. تعريفه مباشرة في ملفplugin.rbلن يعمل. (يستخدم Rails وجود دليلlib/لتحديد جذر المحرك) -
يجب أن يتضمن مسار الملف اسم الوحدة، وفقًا لـ قواعد Zeitwerk
-
يتم استخدام
engine_nameكبادئة لمهام rake وأي مسارات يحددها المحرك (
وثائق rails) -
isolate_namespaceيساعد على منع تسرب الأشياء بين النواة والإضافة (
وثائق Rails)
2. تعريف ملفات روبي في هيكل الدليل الصحيح
سيقوم المحرك الآن بتحميل جميع الملفات تلقائيًا في {plugin}/app/{type}/*. على سبيل المثال، يمكننا تعريف وحدة تحكم
{plugin}/app/controllers/my_plugin_module/examples_controller.rb
module ::MyPluginModule
class ExamplesController < ::ApplicationController
requires_plugin PLUGIN_NAME
def index
render json: { hello: "world" }
end
end
end
سيتم الآن تحميل هذا تلقائيًا كلما حاول أي شيء في Rails الوصول إلى ::MyPluginModule::MyController. للاختبار، حاول الوصول إلى هذه الفئة من وحدة تحكم rails.
لكي يعمل التحميل التلقائي بشكل صحيح، يجب أن تتطابق مسارات الملفات مع التسلسل الهرمي الكامل للوحدة/الفئة وفقًا للقواعد المحددة بواسطة Zeitwerk.
3. تعريف المسارات على محرك الإضافة
قم بإنشاء ملف {plugin}/config/routes.rb
MyPluginModule::Engine.routes.draw do
get "/examples" => "examples#index"
# define routes here
end
Discourse::Application.routes.draw do
mount ::MyPluginModule::Engine, at: "my-plugin"
end
سيتم تحميل هذا الملف تلقائيًا بواسطة المحرك، وستدخل التغييرات حيز التنفيذ دون الحاجة إلى إعادة تشغيل الخادم. في هذه الحالة، سيكون إجراء وحدة التحكم متاحًا على /my-plugin/examples.json.
4. إضافة مسارات تحميل تلقائي إضافية
في بعض الأحيان قد ترغب في تقديم أدلة إضافية لملفات روبي قابلة للتحميل تلقائيًا. المثال الأكثر شيوعًا هو دليل lib/ في الإضافة.
قم بتعديل تعريف المحرك الخاص بك لإلحاق lib/ بمسارات التحميل التلقائي للمحرك:
class Engine < ::Rails::Engine
engine_name PLUGIN_NAME
isolate_namespace MyPluginModule
config.autoload_paths << File.join(config.root, "lib")
end
الآن يمكنك تعريف وحدة مكتبة مثل
{plugin}/lib/my_plugin_module/some_lib_module.rb
module ::MyPluginModule::SomeLibModule
end
والآن أي إشارات إلى ::MyPluginModule::SomeLibModule ستقوم بتحميل الوحدة تلقائيًا من هذا الملف.
5. الربح!
سيتم الآن تحميل جميع هذه الملفات تلقائيًا دون أي استدعاءات require متعمدة. سيتم التقاط التغييرات تلقائيًا بواسطة rails وإعادة تحميلها في مكانها دون الحاجة إلى إعادة تشغيل الخادم.
هذه الوثيقة تخضع للتحكم في الإصدار - اقترح تغييرات على github.