أنا أتعلم كيفية توسيع مُسلسِلات (serializers) ديسكورس (Discourse)، وواجهت سلوكًا لا أفهمه تمامًا.
أضفت هذا الكود لتجاوز PostSerializer#raw:
require_dependency "post_serializer"
class ::PostSerializer
def raw
if scope.can_edit?(object)
object.raw
else
object.raw&.truncate(300)
end
end
end
هذا يعمل بشكل مثالي.
ولكن، إذا قمت بتغييره لاستخدام super:
require_dependency "post_serializer"
class ::PostSerializer
def raw
if scope.can_edit?(object)
super
else
object.raw&.truncate(300)
end
end
end
عندما تكون scope.can_edit?(object)صحيحة، فإن الاستدعاء إلى super يتسبب في إرجاع /posts/:id.jsonخطأ 500.
أعلم أنه يمكنني تجنب المشكلة باستخدام object.raw بدلاً من super، ولكني أريد أن أفهم لماذا يتسبب super في حدوث استثناء هنا، خاصة وأنني أقوم بتجاوز طرق أخرى (مثل cooked و post_stream، إلخ) ويعمل super بشكل جيد في تلك الحالات.
بما أنني ما زلت جديدًا على الأجزاء الداخلية لديسكورس، سأكون ممتنًا جدًا للحصول على شرح حول:
ما الذي يحل محله super بالضبط داخل PostSerializer#raw،
لماذا يؤدي استدعاء super في هذه الحالة إلى خطأ 500،
ولماذا يتصرف raw بشكل مختلف مقارنة بالطرق مثل cooked.
أنا متأكد من أن السبب هو أن raw ليس موجودًا في مُسلسِل (serializer) المنشور العادي. يتم تضمينه فقط عند تعديل المنشور. لعرض منشور، تحتاج فقط إلى cooked؛ سيكون من غير المجدي تضمين raw أيضًا عندما لا يكون مطلوبًا.
يتم تضمين cooked و post_stream في المُسلسِل، لذا يعمل super.
هذه ميزة في Ruby. عندما تستخدم class ::PostSerializer، فإنك تتجاوز التعريف في الفئة الأصلية بدلاً من الوراثة منها. نظرًا لأنك لا ترث من PostSerializer، لا يمكن لـ super العثور على الطريقة المقابلة.
يجب عليك استخدام prepend بدلاً من إعادة فتح فئة مُعرّفة بالفعل.
شكرًا على الشرح!
أنت على حق — إعادة فتح ::PostSerializer كانت هي المشكلة. بعد التبديل إلى prepend، يعمل كل شيء كما هو متوقع.
أنا الآن أستخدم هذه الوحدة:
module PostSerializerExtension
def raw
if scope.can_edit?(object)
super
else
object.raw&.truncate(300)
end
end
end
reloadable_patch do
require_dependency "post_serializer"
::PostSerializer.prepend(::PostSerializerExtension)
end
هذا يعمل بشكل مثالي من جهتي. شكرًا مرة أخرى على التوجيه!