أساسيات إنشاء الإضافات في ريلز

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

تُعدّ الإضافات في ريلز امتدادًا أو تعديلًا للإطار الأساسي. توفر الإضافات:

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

بعد قراءة هذا الدليل، ستتعلم:

  • كيفية إنشاء الإضافات من الصفر.
  • كيفية كتابة وتشغيل الإختبارات للإضافات.

يصف هذا الدليل كيفية إنشاء واختبار إضافة من شأنها:

  • توسيع أصناف روبي الأساسية مثل 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" إلى Active Record

النمط الشائع في الإضافات هو إضافة تابع يسمى act_as_something إلى النماذج. في هذه الحالة، تحتاج إلى كتابة تابع يسمى acts_as_yaffle الذي يضيف التابع squawk إلى نماذج Active Record الخاصة بك.

للبدء، قم بإعداد ملفاتك بحيث يكون لديك:
# 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" إلى أي كائن Active Record يستدعي 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

المراجع

مصادر