أساسيات إنشاء الإضافات في ريلز
تُعدّ الإضافات في ريلز امتدادًا أو تعديلًا للإطار الأساسي. توفر الإضافات:
- وسيلة لمطورين لمشاركة الأفكار المتطورة دون الإضرار بقاعدة الشيفرات الثابتة.
- بنية مجزأة بحيث يمكن إصلاح أو تحديث وحدات الشيفرة وفقًا لجدول إصدارها الخاص.
- منفذ للمطورين الأساسيين حتى لا يضطروا إلى تضمين كل ميزة جديدة بصريح العبارة.
بعد قراءة هذا الدليل، ستتعلم:
- كيفية إنشاء الإضافات من الصفر.
- كيفية كتابة وتشغيل الإختبارات للإضافات.
يصف هذا الدليل كيفية إنشاء واختبار إضافة من شأنها:
- توسيع أصناف روبي الأساسية مثل
Hash
وString
. - إضافة توابع إلى
ApplicationRecord
في إضافاتact_as
التقليدية. - إعطاء معلومات حول مكان وضع المولدات في الإضافات الخاصة بك.
خلال قراءتك لهذا الدليل، تظاهر أنك مولع بمشاهدة الطيور. طيرك المفضل هو نقار الخشب (Yaffle)، وتريد أن تنشئ إضافة تسمح للمطورين الآخرين بمشاركة معلومات عن هذا الطير.
الإعداد
في الوقت الحالي، تُنشَأ إضافات ريلز كجواهر، لذا تدعى «الإضافات الجوهرية» (gemified plugins). يمكن مشاركتها عبر تطبيقات ريلز المختلفة باستخدام RubyGems و Bundler إذا رغبت في ذلك.
توليد إضافة جوهرية
تُشحن ريلز مع الأمر rails plugin new
الذي ينشأ هيكلًا لتطوير أي نوع يوسع عمل ريلز مع القدرة على تشغيل اختبارات متكاملة باستخدام تطبيق ريلز الوهمي. أنشأ الإضافة باستخدام الأمر:
$ rails plugin new yaffle
راجع الاستخدام والخيارات عن طريق طلب المساعدة:
$ rails plugin new --help
اختبار الإضافة الذي أنشئت حديثًا
يمكنك الانتقال إلى المجلد الذي يحتوي على الإضافة، وتشغيل الأمر bundle install
وتشغيل الاختبار الذي أُنشأ باستخدام الأمر bin/test
.
يجب أن ترى شيئًا يشبه:
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
سيخبرك ذلك أن كل شيء أُنشئ بشكل صحيح وأنك على استعداد لبدء إضافة الوظائف.
توسيع الأصناف الأساسية
يشرح هذا القسم كيفية إضافة التابع إلى النوع الأساسي String
الذي سيصبح متوافرًا للاستعمال في أي مكان في تطبيق ريلز.
في هذا المثال، ستضيف تابعًا إلى النوع String
يدعى to_squawk
. للبدء، قم بإنشاء ملف اختبار جديد مع بعض التأكيدات:
# yaffle/test/core_ext_test.rb
require "test_helper"
class CoreExtTest < ActiveSupport::TestCase
def test_to_squawk_prepends_the_word_squawk
assert_equal "squawk! Hello World", "Hello World".to_squawk
end
end
نفِّذ الأمر bin/test
لتشغيل الاختبار. يجب أن يفشل هذا الاختبار لأننا لم ننفذ التابع to_squawk
:
E
Error:
CoreExtTest#test_to_squawk_prepends_the_word_squawk:
NoMethodError: undefined method `to_squawk' for "Hello World":String
bin/test /path/to/yaffle/test/core_ext_test.rb:4
.
Finished in 0.003358s, 595.6483 runs/s, 297.8242 assertions/s.
2 runs, 1 assertions, 0 failures, 1 errors, 0 skips
عظيم! الآن أنت على استعداد لبدء عملية التطوير.
في الملف lib/yaffle.rb، أضف "require "yaffle/core_ext
:
# yaffle/lib/yaffle.rb
require "yaffle/railtie"
require "yaffle/core_ext"
module Yaffle
# ضغ شيفرتك هنا
end
وأخيرًا، أنشئ الملف core_ext.rb وأضف التابع to_squawk
:
# yaffle/lib/yaffle/core_ext.rb
class String
def to_squawk
"squawk! #{self}".strip
end
end
لاختبار أن تابعك يُنفِّذ ما طلبنا منه، شغل اختبارات الوحدة مع bin/test
من مجلد الإضافات.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
لرؤية هذا بشكل عملي، انتقل إلى المجلد test/dummy، واستدعي وحدة التحكم ثم استدعي التابع to_squawk
:
$ bin/rails console
>> "Hello World".to_squawk
=> "squawk! Hello World"
إضافة تابع "acts_as" إلى السجل الفعال
النمط الشائع في الإضافات هو إضافة تابع يسمى act_as_something
إلى النماذج. في هذه الحالة، تحتاج إلى كتابة تابع يسمى acts_as_yaffle
الذي يضيف التابع squawk
إلى نماذج السجل الفعال الخاصة بك.
للبدء، قم بإعداد ملفاتك بحيث يكون لديك:
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
end
# yaffle/lib/yaffle.rb
require "yaffle/railtie"
require "yaffle/core_ext"
require "yaffle/acts_as_yaffle"
module Yaffle
# ضع شيفرتك هنا
end
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
end
end
إضافة تابع الصنف
تتوقع هذه الإضافة أنك أضفت تابعًا إلى نموذجك يدعى last_squawk
. ومع ذلك، قد يكون مستخدمو الإضافة قد عرفوا بالفعل تابعًا على نموذجهم يدعى last_squawk
الذي يستخدمونه لشيء آخر. ستسمح هذه الإضافة بتغيير الاسم عن طريق إضافة تابع صنف يسمى yaffle_text_field
.
للبدء، اكتب اختبارًا فاشلًا يعرض السلوك الذي تريده:
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
end
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
assert_equal "last_tweet", Wickwall.yaffle_text_field
end
end
عند تشغيل bin/test
، يجب أن تشاهد ما يلي:
# Running:
..E
Error:
ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NameError: uninitialized constant ActsAsYaffleTest::Wickwall
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:8
E
Error:
ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NameError: uninitialized constant ActsAsYaffleTest::Hickwall
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:4
Finished in 0.004812s, 831.2949 runs/s, 415.6475 assertions/s.
4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
هذا يخبرنا بأننا لا نملك النماذج اللازمة (Hickwall و Wickwall) التي نحاول اختبارها. يمكننا بسهولة إنشاء هذه النماذج في تطبيق ريلز "dummy" الخاص بنا عن طريق تشغيل الأوامر التالية من المجلد test/dummy:
$ cd test/dummy
$ bin/rails generate model Hickwall last_squawk:string
$ bin/rails generate model Wickwall last_squawk:string last_tweet:string
يمكنك الآن إنشاء جداول قاعدة البيانات الضرورية في قاعدة بيانات الاختبار بالانتقال إلى تطبيقك الوهمي وتهجير قاعدة البيانات. في البداية، شغل:
$ cd test/dummy
$ bin/rails db:migrate
أثناء تواجدك هنا، غير النموذجين Hickwall و Wickwall حتى يعرفوا أنه من المفترض أن يعملوا مثل yaffles.
# test/dummy/app/models/hickwall.rb
class Hickwall < ApplicationRecord
acts_as_yaffle
end
# test/dummy/app/models/wickwall.rb
class Wickwall < ApplicationRecord
acts_as_yaffle yaffle_text_field: :last_tweet
end
سنضيف أيضًا رمزًا لتحديد التابع act_as_yaffle
.
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
class_methods do
def acts_as_yaffle(options = {})
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
يمكنك بعد ذلك الرجوع إلى المجلد الجذر (cd ../..
) من الإضافة الخاصة بك وإعادة تشغيل الاختبارات باستخدام bin/test
.
# Running:
.E
Error:
ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NoMethodError: undefined method `yaffle_text_field' for #<Class:0x0055974ebbe9d8>
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:4
E
Error:
ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NoMethodError: undefined method `yaffle_text_field' for #<Class:0x0055974eb8cfc8>
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:8
.
Finished in 0.008263s, 484.0999 runs/s, 242.0500 assertions/s.
4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
اقتربنا أكثر. سننفذ الآن شيفرة التابع act_as_yaffle
لجعل الاختيار يتحقق.
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
class_methods do
def acts_as_yaffle(options = {})
cattr_accessor :yaffle_text_field, default: (options[:yaffle_text_field] || :last_squawk).to_s
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
عند تشغيل bin/test
، يجب أن تشاهد تحقق جميع الاختبارات:
4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
إضافة تابع نسخة
ستضيف هذه الإضافة تابعًا باسم "squawk" إلى أي كائن سجل فعال يستدعي act_as_yaffle
. سيعين التابع "squawk" ببساطة قيمة أحد الحقول في قاعدة البيانات.
للبدء، اكتب اختبارًا فاشلًا يعرض السلوك الذي تريده:
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
end
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
assert_equal "last_tweet", Wickwall.yaffle_text_field
end
def test_hickwalls_squawk_should_populate_last_squawk
hickwall = Hickwall.new
hickwall.squawk("Hello World")
assert_equal "squawk! Hello World", hickwall.last_squawk
end
def test_wickwalls_squawk_should_populate_last_tweet
wickwall = Wickwall.new
wickwall.squawk("Hello World")
assert_equal "squawk! Hello World", wickwall.last_tweet
end
end
شغل الاختبار للتأكد من فشل الاختبارين الماضيين مع وجود خطأ يحتوي على الرسالة: "NoMethodError: squawk method undefined"، ثم حدِّث الملف act_as_yaffle.rb لتبدو بالشكل التالي:
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
included do
def squawk(string)
write_attribute(self.class.yaffle_text_field, string.to_squawk)
end
end
class_methods do
def acts_as_yaffle(options = {})
cattr_accessor :yaffle_text_field, default: (options[:yaffle_text_field] || :last_squawk).to_s
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
شغل bin/test
مرة أخيرة ويجب أن ترى:
6 runs, 6 assertions, 0 failures, 0 errors, 0 skips
ملاحظة: يُعدُّ استخدام write_attribute
للكتابة على حقل في النموذج مثالًا واحدًا فقط عن كيفية تفاعل الإضافة مع النموذج، ولن يكون دائمًا التابع الصحيح للاستخدام. على سبيل المثال، يمكنك أيضًا استخدام:
send("#{self.class.yaffle_text_field}=", string.to_squawk)
المولدات
يمكن تضمين المولدات في الجوهرة الخاص بك ببساطة عن طريق إنشائها في المجلد lib/generators للإضافة الخاص بك. يمكن العثور على مزيد من المعلومات حول إنشاء المولدات في دليل المولدات.
نشر الجوهرة الخاص بك
يمكن مشاركة جوهرة الإضافات قيد التطوير بسهولة من أي مستودع Git. لمشاركة الجوهرة Yaffle مع الآخرين، رحِّل ببساطة الشيفرة إلى مستودع Git (مثل GitHub) وأضف السطر التالي إلى الملف Gemfile الخاص بالتطبيق المعني:
gem "yaffle", git: "https://github.com/rails/yaffle.git"
بعد تنفيذ bundle install
، ستكون وظائف الجوهرة الخاص بك متاحةً للتطبيق.
عندما تكون الجوهرة جاهزة للمشاركة كإصدار رسمي، يمكن نشرها في RubyGems. لمزيد من المعلومات حول نشر الجواهر في RubyGems، راجع مقال نشر جوهرة الخاص بك.
توثيق RDoc
بمجرد أن تصبح الإضافة ثابتة وجاهزة للنشر، أسدِ معروفًا إلى الجميع ووثقها. لحسن الحظ، من السهل كتابة توثيق الإضافة.
تتمثل الخطوة الأولى في تحديث الملف README بمعلومات تفصيلية حول كيفية استخدام الإضافة. بعض الأشياء الأساسية التي يجب تضمينها هي:
- اسمك.
- كيفية التثبيت.
- كيفية إضافة الوظائف إلى التطبيق (عدة أمثلة لحالات الاستخدام الشائعة).
- التحذيرات أو الخدع أو النصائح التي قد تساعد المستخدمين وتوفر الوقت عليهم.
بمجرد أن يصبح الملف README جيدًا وغنيًّا بالمعلومات، انتقل وأضف تعليقات rdoc إلى جميع التوابع التي سيستخدمها المطورون. من المعتاد أيضًا إضافة تعليقات :nodoc:#
على أجزاء الشيفرة التي لن تُضمن في واجهة برمجة التطبيقات العامة.
بعد أن تكون تعليقاتك جيدة ومفيدة لبدء الاستعمال، انتقل إلى مجلد الإضافة وشغّلها:
$ bundle exec rake rdoc