OOZOU
تواصلوا معنا
العودة إلى المدونة

فصل منطق العرض في Ruby on Rails باستخدام Presenters

حشو نماذج ActiveRecord بدوال مخصصة للعرض ممارسة سيئة وعلامة على مشكلة في الكود. تضيف الـ Presenters طبقة تجريد بين النماذج والواجهات لتساعدنا على بناء تطبيق أسهل في الصيانة.

19 يوليو 2020
5 دقائق للقراءة
فصل منطق العرض في Ruby on Rails باستخدام Presenters

بصفتكم مطوّري Rails، ستجدون كثيرًا نماذج (models) تحتوي على دوال يبدو أن كل ما تفعله هو بعض التنسيق. تُستخدم هذه الدوال عادة في الواجهات (views) لعرض البيانات بصيغة مألوفة أكثر للمستخدمين النهائيين. من المغري جدًا تعريف دوال التنسيق والدوال المنطقية (boolean) هذه داخل النموذج، لأننا اعتدنا على فكرة أن النماذج هي ما يُعرض في الواجهات. لكن إذا توقفنا وتأملنا دور كل كائن في تطبيقنا، فسنصل بسهولة إلى أن تعريف هذه الدوال يخلط بين المسؤوليات. ومع أنني لا أرى أن خلط المسؤوليات يجب أن يُمنع دائمًا، فإنني أعتقد أن حل هذه المشكلة سهل، ولذلك يستحق العناء. الـ Presenters تجريد بسيط يحل مشكلتنا بجهد قليل وفائدة كبيرة. فهي تجعل تطبيقاتنا أسهل كثيرًا في الصيانة عبر تقليل المسؤوليات، وهذا بدوره يقلل الفوضى ويعزل المنطق الذي يخص جزءًا صغيرًا واحدًا فقط من التطبيق ككل.

ما هو الـ Presenter؟

الـ Presenter كائن يقع بين النموذج والواجهة ليغلّف منطق التنسيق وغيره من منطق العرض المعقد. على سبيل المثال، إذا كان لدينا BankCard ونريد إخفاء جزء من الرقم، يمكننا إنشاء BankCardPresenter وتعريف دالة masked_card_number

class BankCardPresenter
  def initialize(bank_card)
    @bank_card = bank_card
  end

  def masked_card_number
    "**-**-**-#{@bank_card.card_number[-4..-1]}"
  end

  def valid?
    Time.current.before?(@bank_card.expiration)
  end

  def bank_name
    return 'KBank' if @bank_card.bank_name == 'Kasikorn'

    @bank_card.bank_name
  end
end
BankCardPresenter.new(BankCard.first).masked_card_number
# => **-**-**-4242

أو ربما نريد عرض رمز QR لنظام الدفع لدينا. يمكننا إنشاء TransactionPresenter وتعريف دالة 'qr_code'

class TransactionPresenter
  def initialize(transaction)
    @transaction = transaction
  end

  def qr_code
    QRCode.new(transaction.transaction_identifier)
  end
end

مع الوقت، تبدأ هذه الدوال في إثقال نماذجنا. لا يمثل ذلك مشكلة عادة إلى أن تصبح لديكم مئات الدوال في نماذجكم العملاقة (god models). على الأرجح نحتاج إلى qr_code في واجهة واحدة فقط، وحتى لو احتجنا إليها في كل الواجهات، فلن نحتاج إليها في النماذج أو في المهام الخلفية (background jobs) وغيرها. يجب أن يُصمَّم منطق التطبيق ليعمل مع البيانات كما تأتينا مباشرة من قاعدة البيانات. ولا نحتاج إلى التنسيق إلا عند عرض البيانات للمستخدمين النهائيين، لتظهر بصيغة مألوفة يسهل استيعابها.

هل يمكننا تحسين ذلك؟

تقدم Ruby صنفًا جميلًا يساعدنا على إنشاء الـ Presenters، وهو SimpleDelegator! وربما تكون الـ Presenters من أنسب حالات استخدام SimpleDelegator. SimpleDelegator صنف أساسي في Ruby يتيح لنا تفويض جميع الدوال غير المعرّفة في الكائن الحالي إلى الكائن المغلَّف. ولتغليف كائن، يكفي أن نمرره عند الإنشاء. يتيح لنا ذلك إنشاء Presenters لا تحتاج إلى منطق إنشاء مخصص، ويمكننا التعامل مع الـ Presenter كأنه الكائن المعروض نفسه، فنستدعي transaction_identifier على الـ Presenter مباشرة بدلًا من الكائن @transaction. وهذا يجعل الـ Presenters أنظف وأبسط.

class BankCardPresenter < SimpleDelegator
  def masked_card_number
    "**-**-**-#{card_number[-4..-1]}"
  end
end
BankCardPresenter.new(BankCard.first).masked_card_number
# => **-**-**-4242

قد ترغبون أحيانًا في تجاوز (override) دالة موجودة في الكائن المغلَّف، ويتيح لنا SimpleDelegator استدعاء super للوصول إلى الكائن المعروض، مثلًا:

class BankCardPresenter < SimpleDelegator
  def card_number
    "**-**-**-#{super[-4..-1]}"
  end
end
BankCardPresenter.new(BankCard.first).card_number
# => **-**-**-4242

متى يجب استخدام الـ Presenter؟

شخصيًا أستخدمها في الواجهات والـ serializers حين يتطلب الموقف بعض التنسيق للخصائص. وكلما احتجت إلى خاصية غير موجودة أصلًا في النموذج، أنشئ Presenter. تنظيم الـ Presenters أصعب قليلًا، وهو أمر يجب الانتباه إليه، وستحتاجون إلى التجربة. على سبيل المثال، إذا أنشأتم Presenter باسم UserRegistrationPresenter واستخدمتموه في 4 واجهات مختلفة، ثم احتاجت واجهة واحدة منها إلى خاصية إضافية، فيمكنكم إما إضافة تلك الخاصية رغم أنها تخص واجهة واحدة من أربع، أو إنشاء Presenter جديد بالكامل. يمكنكم بالطبع إنشاء أصناف فرعية منها لمشاركة الدوال، أو حتى استخدام concerns أو وحدات PORO أو أساليب أخرى للمشاركة بين الـ Presenters المختلفة. ومن تجربتي، لن تحتاجوا في أغلب الأحيان إلى عدد كبير من الـ Presenters لإنجاز المهمة. أميل إلى إضافة تلك الدالة الإضافية فحسب، حتى لو كانت تخص بضع واجهات فقط. فهذا يظل تحسنًا كبيرًا مقارنة بحشر هذه الدوال في النماذج. من الأمور اللطيفة في الـ Presenters أنها تعرض الكائن الممرَّر إليها، لذا يمكنكم نظريًا تمرير Presenter إلى Presenter آخر. لا أنصح بذلك بالضرورة، لأنني متأكد من أنه سيصبح من الصعب تتبع وجهة الاستدعاءات بدقة بعد مستوى معين من التداخل. وكالعادة، القرار لكم. تمنحنا Ruby قدرًا هائلًا من المرونة والقوة، فاستخدموها بمسؤولية! الـ Presenters مجرد أداة إضافية نستخدمها لبناء تطبيقات سهلة الصيانة، وأرجو أن تجدوها مفيدة كما أجدها أنا.

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد