خان المُبرمجين (علي فاضل)
543 subscribers
93 photos
9 videos
116 links
قناة أنشر فيها ما أتعلمه خلال عملي على مشاريعي الخاصة 👀
Download Telegram
منشور خفيف لطيف لهذا اليوم المبارك 🕌

دائما كنت أنسى أضيف بعض الملفات لملف gitignore في المشاريع اللي بشتغلها، ومن أشهر هذه الملفات ملف DS_Store على نظام تشغيل Mac، وأحيانا لما تكثر هذه الملفات في مستودع Git الخاص بالمشروع بكون حذفها وتنظيف المستودع منها مرهق (مش مستحيل).

إلى أن وجدت هذا الموقع:
https://www.toptal.com/developers/gitignore

انت بتحكيله شو التقنيات اللي بتستخدمها، مثلا Ruby و Rails على نظام تشغيل Mac، وهو بيعملك ملف gitignore فيه كل ما يتعلق بهذه التقنيات جاهز للاستخدام، بدون ما تنسى شيء.

والسلام عليكم 👋🏻
3
السلام عليكم ورحمة الله وبركاته،

إخواني المتصدرين وصناع المحتوى واللي الناس تتابع منصاتكم وحساباتكم، هذه نصيحة أنا شخصيا أواجهها لما أقرأ منشوراتكم وقد أقع في نفس المشاكل فنبهوني.

- الاستخدام المفرط للهجة العامية في المنشورات مضر غير نافع، لا ضير من استخدام العامية بجانب الفصحى، ولكن خلينا نحاول نرتقي بطريقة كتابتنا.

- الأخطاء الإملائية وعدم تنسيق المنشور شيء سيء مش جيد، حاول تنسق منشورك وتهتم فيه، مثلا ما يكون في مسافات كثيرة متتابعة بدون داعي.

- إذا في مصطلح عربي بديل عن الانجليزي حاول تستخدمه وتتبعه بالمصطلح الانجليزي، بعرف المجال التقني صعب فيه هذا الأمر ولكن حاول.

بحب أقرأ منشوراتكم ولكن داخلي هذا الأمر من فترة وحبيت أحكيه لعلنا نرتقي بالمحتوى أكثر، وما ننسى ان ما نكتب اليوم هو بيانات تدريب النماذج غدا، شئنا أم أبينا 😁

ملاحظة: نماذج مثل ChatGPT و Claude بتساعد كثير في مراجعة المحتوى قبل نشره.
7👍1
هل أنت بحاجة Redis ومثيلاتها لأمور مثل الـ Caching والـ Background Jobs في عصر الـ NVMe؟ 🤔

بدايةً، Redis مقاطعة، ولها بدائل كثيرة مثل valkey وهي متوافقة مع Redis بداية من الإصدار 7.2، ولكن ذكرتها لشهرتها ومعرفت الناس بها.

مع الإصدار السابع والثامن لإطار عمل Ruby on Rails، أعلن DHH عن مجموعة مكتبات تحت مسمى Solid وهي:
- SolidCache
- SolidQueue
- SolidCable

الأولى من اسمها مخصصة للـ Caching وهي بديلة لأشياء مثل Redis و Memcached والثانية مخصصة للـ Background Jobs وهي بديلة لأشياء مثل Sidekiq والثالثة والأخيرة مخصصة للـ WebSockets وهي بديلة لأشياء مثل CableReady.

طيب ما المميز في هذه المجموعة من المكتبات؟ اسمها حلو مثلا؟

حقيقة المميز فيها هو اعتمادها على قاعدة البيانات مثل SQLite أو PostgreSQL بدلا من الذاكرة، على عكس كل المكتبات الثانية، فكل من Redis و Memcached و Sidekiq و CableReady تعمل على ذاكرة الخادم بدلا من المساحة التخزينية اللي تستخدمها قاعدة البيانات بشكل أساسي، وكلهم معتمدين على Redis كمكان لتخزين بياناتهم (تحديدا Sidekiq و CableReady).

فكرة مجموعة مكتبات Solid أصبحت ممكنة في عصر المساحات التخزينية المعتمدة على الـ NVMe. كمثال، شركة 37Signals بدأت في استخدام SolidCache في منتجها Basecamp من سنة ونص تقريبا. المُلاحظ كان أن سرعة القراءة من SolidCache كانت أبطأ من Redis بنسبة 40%، ولكن مساحة الـ Cache أصبحت أكبر بـ 6 مرات (10TB!)، وسعرها أرخص بنسبة 80%.

بالمُحصّلة، زمن الاستجابة في Basecamp نزل من 375ms للـ p95 إلى 225ms.

ممكن تقرأ عن تجربتهم من هنا:
https://dev.37signals.com/solid-cache

مثال آخر هو مكتبة SolidQueue، حاليا 37Signals تستخدمها في منتجهم Hey.com وقادرين على معالجة أكثر من 20 مليون Background Job في اليوم، كله بدون استخدام الذاكرة والاعتماد المباشر على قاعدة البيانات.

طيب ليش بحكيلك هالكلام؟ عشان أبهرك مثلا؟

صراحة نعم حاب أبهرك، مع الإصدار الثامن من Ruby on Rails انت فقط محتاج قاعدة بيانات SQLite موجودة على المساحة التخزينية للخادم لدعم الـ Caching والـ Background Jobs والـ WebSockets، بتكلفة قليلة وبدون أي اعتماديات إضافية مثل Redis.

أكيد أُطر عمل ثانية رح تبدأ تتبع نفس النهج مستقبلا، والجميل أن شركة مثل 37Signals تستخدم هذه المكتبات لدعم منتجات حقيقية لها مئات الآلاف (إن لم يكن ملايين) المستخدمين.

والسلام عليكم 👋🏻
4👍1
#تجارب_فاشلة

لسهولة بدأ مشاريع جديدة وتجربة أفكار مختلفة في Ruby on Rails، وجدت أن عندي مشاريع كثيرة وكل فترة بحتاج أبدأ شيء جديد ولكن يستهلك مني وقت في إعداد المشروع من ناحية تثبيت الاعتماديات المطلوبة وتجهيزها بشكل كامل على المشروع.

فقررت في منتصف الليل اني أعمل مكتبة بمجرد ما أضيفها على مشروع Rails الجديد وأشغّل أمر مثل:
rails g package:install


يكون عندي المشروع جاهز من ناحية الاعتماديات وتجهيزها في المشروع، وحتى تحديث إصدارات الاعتماديات ممكن يتم مرة واحدة داخل المكتبة الجديدة وبشكل مباشر تنتقل هذه التحديثات لمشاريعي كلها، الفكرة من بعيد ممتازة.

فعلا، عملت المكتبة وسميتها permadeps (اخصارًا لـ Permanent Dependencies أو الاعتماديات الدائمة) وهذا مستودعها على GitHub:
https://github.com/AliOsm/permadeps

وكنت مبسوط عليها وبدأت أستخدمها في أكثر من مشروع، ولكن بدأت تظهر المشاكل:

🔸 في Rails (وغيرها) ممكن تحدد هل الاعتمادية هي اعتمادية للتطوير فقط (Development Dependency) أو اعتمادية تحتاجها حتى في الـ Production؟ وهذا الأمر كان غير ممكن في حالة permadeps، فكنت مضطر أستخدم كل الاعتماديات في الـ Production واللي هو أمر مش مؤثر بكثرة، مجرد استهلاك إضافي للذاكرة (بحدود 15MB).

🔸 يوجد مكتبتان أساسيتان لكتابة الاختبارات في Rails وهي مكتبة minitest ومكتبة RSpec. بعض مشاريعي كانت تستخدم الأولى والبعض الآخر يستخدم الثانية. فاضطريت أحط الإثنين كاعتماديات في permadeps واللي هو أمر مش لطيف، ولكن ممكن التغاضي عنه، وله نفس مساوئ النقطة السابقة.

🔸 لما عملت permadeps كنت أستخدم Frontend Stack يعتمد على الاعدادات الإفتراضية من Rails واللي بتستخدم ERb، بعد فترة قررت الانتقال إلى Phlex. مبدئيًّا ممكن تحكي الأمور سهلة بس عدّل الاعتماديات في permadeps ولكن بهذه الطريقة أنا محتاج أعدل كل المشاريع عشان تستخدم Phlex واللي هو أمر مرهق وغير ضروري في حالات كثيرة.

🔸 أخيرا، بعض الاعتماديات مثل PgHero وهي عبارة عن لوحة متابعة لقاعدة بيانات PostgreSQL أستخدمها مع المشاريع اللي بتستخدم قاعدة بيانات PostgreSQL فقط، ولكن حتى في المشاريع اللي بتستخدم SQLite مثلا كنت مضطر أنزلها لأنها من اعتماديات permadeps.

بعد هذه التجربة الفاشلة والمشاكل اللي واجهتها، قررت إيقاف مكتبة permadeps والاعتماد على شيء مختلف وهو Rails Templates.

من خلال Rails Templates بتقدر تعمل Setup للكثير من الاعتماديات وإضافة ملفات للمشروع من بدايته وتجهيزه بالطريقة اللي بدك ياها بمجرد إضافة خيار واحد إلى أمر إنشاء المشروع في Rails، فبدل ما تكتب:
rails new blog


ممكن تكتب:
rails new blog -m ~/template.rb


إذا كان الـ Template موجود على الجهاز، أو:
rails new blog -m URL


إذا كان الـ Template موجود على رابط.

ممكن تقرأ أكثر عن Rails Templates من هنا:
https://guides.rubyonrails.org/rails_application_templates.html

والسلام عليكم 👋🏻
1
خان المُبرمجين (علي فاضل)
Photo
18 حرفا من الممكن أن تغير أداء تطبيقك!

كنت أتحدث مع صديقي وزميلي في العمل البارحة، وكان يشرح لي مشكلة حدثت مع صديقه في أحد مشاريعه وكيف كان يساعده من خلال استخدام JMeter لضغط خادم التطبيق واختباره. فقلت له: "يجب أن نجرّب الأمر نفسه على باحث"، وفعلًا بدأنا في ذلك ولكن كانت النتائج سيئة جدًا؛ الخادم لا يستطيع معالجة أكثر من ألفيْ طلب على الصفحة الرئيسية خلال دقيقة!

ذهبت إلى المنزل ودخلت في دوّامة البحث عن السبب، فأنا متأكد أن باحث كان يستطيع معالجة طلبات أكثر من ذلك في السابق. ففتحت الخادم من خلال SSH وشغّلت أداة htop وبدأت الاختبار مرة ثانية مع مراقبة النتائج من htop، وكانت المفاجأة أن باحث لا يستهلك معالج الخادم بالكامل، وإنما يستهلك ما يقارب 10% منه فقط!

فأول ما خطر لي التأكد من قيمة أحد إعدادات Ruby on Rails وهو WEB_CONCURRENCY، وكانت المفاجأة الثانية أن هذا الإعداد قد اختفى من مستودع باحث وبشكل تلقائي Rails تستخدم 1 كقيمة لهذا الإعداد في حال عدم تحديده من قبل المطوّر!

رفعت الـ WEB_CONCURRENCY من 1 إلى 8 وأعدت الاختبار على صفحات مختلفة من باحث، واختلفت النتائج تمامًا.

بالقيمة القديمة كان باحث يُعالج كحد أقصى ألف طلب في الدقيقة، بمتوسط زمن استجابة 723ms، على أثقل صفحات الموقع وهي صفحة عرض المواد والتي تتعامل مع قاعدة البيانات بكثرة. بينما باستخدام القيمة الجديدة فباحث يستطيع معالجة أكثر من 7,500 طلب في الدقيقة، بمتوسط زمن استجابة 375ms، كما هو موضّح في الصورتين.

هذه الأرقام مع الأخذ بعين الاعتبار أن خادم باحث يحتوي على المنصة وقاعدة البيانات ومحرك البحث وكل ما يتعلق بباحث.

لا أدري كيف ومتى تغيّرت إعدادات باحث وأُزيل منها الـ WEB_CONCURRENCY، ولكن الحمد لله أننا وجدنا المشكلة 😁

ولمن يسأل ما هي الـ 18 حرفًا، فهي:
WEB_CONCURRENCY: 8


أما WEB_CONCURRENCY فهو إعداد مهم في تطبيقات Rails يحدد عدد عمليات Puma (خادم الويب الافتراضي لـ Rails) التي يمكن تشغيلها بالتوازي. يتحكم هذا الإعداد في عدد العمليات التي يمكن لخادم Puma إنشاؤها لمعالجة الطلبات الواردة. زيادة قيمة WEB_CONCURRENCY تسمح للتطبيق بمعالجة المزيد من الطلبات في وقت واحد، مما يحسن الأداء العام وقدرة التحمل للتطبيق. ومع ذلك، من المهم موازنة هذه القيمة مع موارد الخادم المتاحة كالذاكرة والمعالج.

والسلام عليكم 👋🏻

ملاحظة: الصور من موقع https://loader.io وهذه روابط الاختبارات لمن يريد الاطلاع عليها:
- https://loader.io/reports/914e27236aa9ebdccd62072177a1ace0/results/34ad9ac42d59999073b8ef629f66890c
- https://loader.io/reports/914e27236aa9ebdccd62072177a1ace0/results/b8ca0bb6532dc1f351027bebfc94ce3f
3
خان المُبرمجين (علي فاضل)
Photo
إعادة فتح الـ Classes في Ruby 🤔

من الأشياء اللطيفة في لغة Ruby واللي بتفتح المجال للكثير من الأمور هي إمكانية إعادة فتح الـ Classes وإضافة أشياء جديدة لها مثل الدوال.

على سبيل المثال، الـ Class الخاص بالـ Strings ما فيه دالة ?palindrome في لغة Ruby، ولكن في الصورة الأولى أعدت فتح الـ Class (رغم انه Class جاي من اللغة نفسها) وأضفت له الدالة الجديدة واستطعت استخدامها على كائن جديد من نوع String.

هذا الأمر واللي يسمى بمُصطلح يصعب علي تعريبه "Monkey Patching"، مستخدم بكثرة في مكان زي Rails لتوفير تحسينات كثيرة للمطوّر، من أبسطها على سبيل المثال إضافة دالة inquiry للـ String Class واللي إذا طبقتها على نص مثلا "production" بتعطيك كائن جديد من نوع StringInquirer واللي ممكن تسأله عن قيمته النصية بشكل مباشر زي ماهو موضح في الصورة الثانية بدلا من مقارنة نص بنص.

ممكن تشوف كيف الإضافة صارت من هنا:
https://github.com/rails/rails/blob/v8.0.1/activesupport/lib/active_support/core_ext/string/inquiry.rb

وتشوف كيف الـ StringInquirer Class بيشتغل من هنا:
https://github.com/rails/rails/blob/v8.0.1/activesupport/lib/active_support/string_inquirer.rb

وهو يستخدم ميزة الـ method_missing اللي حكيت عنها في منشور سابق واللي ممكن تقرأه من هنا:
https://t.me/programmerskhan/17

أخيرا، بالرغم من أن إعادة فتح الـ Classes (أو الـ Monkey Patching) يوفر مرونة كبيرة لإضافة وتعديل اللغة ومكتباتها، إلا أن لها بعض العيوب اللي لازم تاخذها بعين الاعتبار.

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

والسلام عليكم 👋🏻
1👍1
خان المُبرمجين (علي فاضل)
Photo
من مشاكل التخزين المؤقت (أو الـ Caching) 😁

منصة باحث تسمحلك بالبحث في تفريغات دروس ومحاضرات المشايخ، وخلال مشاهدة الدروس والمحاضرات بتقدر تقرأ التفريغ وتتابعه، ممكن تعرف عن المنصة أكثر من خلال هذا المقطع:
https://youtu.be/vl90LkLgfE4

من المميزات اللي حبيت أضيفها للمنصة ميزة الإشارات المرجعية (Bookmarks)، بمعنى وانت بتحضر الدرس أو المحاضرة ممكن تحط إشارة مرجعية على مكان معين في الدرس وترجعله مستقبلا.

تطبيق الميزة كان سهل من ناحية قاعدة البيانات والـ Backend، ولكن لما وصلت لمرحلة تعديل واجهة المستخدم كانت المفاجأة، صفحة عرض المادة في عليها تخزين مؤقت (مارح أحكي Caching في المنشور 🙂).

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

أول شيء ممكن يخطر في بالك هو إضافة المستخدم لمفتاح التخزين المؤقت بحيث تكون المادة بالإضافة للمستخدم مفتاح فريد يضمن ظهور التعديلات على واجهة المستخدم. ولكن كمية البيانات اللي ممكن تتخزن في الذاكرة كبيرة جدا حسب عدد مستخدمي تطبيقك (عدد الصفحات المُخزّنة = عدد المواد * عدد المستخدمين)، فهذا الحل غير مُجدي.

الحل الثاني واللي طبقته وقتها هو تخزين الجزء الأكبر من الصفحة بحيث ما ينعمله Rendering، ولكن في بداية الصفحة وضعت عنصر HTML مخفي ووضعت فيه أرقام الإشارات المرجعية الخاصة بالمستخدم للمادة الحالية، ثم من خلال JavaScript أُغيّر واجهة المستخدم بحيث تظهر العناصر بالشكل المطلوب وتستخدم الروابط الصحيحة لإضافة وحذف الإشارات المرجعية.

بهذه الطريقة التخزين المؤقت شغّال والمستخدم قادر يشوف إشاراته المرجعية والعصافير تزقزق والسماء صافية والسلام عليكم 👋🏻

ملاحظة: بعد فترة أزلت التخزين المؤقت كله من باحث 😂 ولكن نفس الكود لساته موجود.
1👍1🔥1
خان المُبرمجين (علي فاضل)
Photo
تعقيبًا على منشور البارحة والذي يمكن أن تقرأه من هنا:
https://t.me/programmerskhan/38

سأل أحد الأصدقاء: "لماذا أزلت التخزين المؤقت (Caching) من منصة باحث؟"، والجواب باختصار شديد هو الانتقال من استخدام ERb للواجهات إلى مكتبة Phlex.

ذكرت مكتبة Phlex من قبل وهي عبارة عن شيئ شبيه بـ JSX للغة Ruby، حيث يمكنك بناء عناصر (Components) منفصلة للصفحات بلغة Ruby وإعادة استخدامها ثم يتحول ما كتبته من Ruby إلى HTML خلال عملية الـ Rendering، مع توفير مميزات إضافية يمكن أن تقرأ عنها في موقع المكتبة: https://beta.phlex.fun

افتراضيًّا، Rails تدعم التخزين المؤقت في ERb من خلال دالة cache وهي تهتم بإنشاء Digests لملفات الصفحات ومتابعة التغييرات التي تحصل لها وإنشاء المفاتيح (Keys) المطلوبة لتخزين واسترجاع الصفحات أو أجزاءها، ولكن هذا الأمر لا يتوفّر في مكتبات مثل Phlex و ViewComponent المُقدّمة من GitHub ولهم أسبابهم في ذلك.

فلسفة مطوّر Phlex هي أن المكتبة سريعة كفاية ولا حاجة لاستخدام التخزين المؤقت معها، فمثلا Phlex أسرع من ERb بـ 12 مرة وأسرع من ViewComponent بـ 6 مرات تقريبا حسب الاختبارات، فمع وجود هذه السرعة، إضافة التخزين المؤقت قد يكون مُضرًّا بكفاءة المكتبة مع إضافة تعقيدات لا داعٍ لها، وهذا الادعاء صحيح إجمالا، ولكن هناك تفصيل.

في البداية، عندما نقلت باحث بالكامل من ERb إلى Phlex وأطلقت الإصدار الجديد، لاحظت انخفاضًا كبيرًا في زمن الاستجابة وكان سببه الأساسي تقليل زمن تجهيز الصفحة وإرسالها للمستخدم، وهذا ما كنت أنتظره من انتقالي إلى Phlex (مع التخلص من ERb 😂، ألقِ نظرةً على الصور لتفهم الفرق)، رغم إزالتي للتخزين المؤقت بالكامل.

ولكن بعد مدة وجدت أنني أحتاج للتواصل مع قاعدة البيانات بشكل أكثر من السابق، والسبب أن بعض الاستعلامات (Queries) على قاعدة البيانات كان يُستغنى عنها لأنها تتم داخل الصفحة المخزنة بالفعل، وهنا تأتي التفاصيل المتعلقة بالتخزين المؤقت و Phlex.

بشكل عام، إذا كنت مضطرًّا لجلب البيانات من قاعدة البيانات لبناء مفتاح التخزين المؤقت فلا داعي لاستخدامه مع وجود Phlex، لأن جلب الصفحة أو أجزاءها المخزنة من Redis مثلا هو أبطأ من عمل Render لها، أما إذا كان المفتاح يعتمد على عدد محدود من البيانات وهناك استعلامات كثيرة تحصل داخل الصفحة خلال عملية الـ Rendering فوجود التخزين المؤقت مفيد وسيُسرّع العملية أكثر.

لهذا السبب، ستدعم مكتبة Phlex التخزين المؤقت مستقبلا بناء على بعض النقاشات الحاصلة في مجتمع مطوّري المكتبة على Discord.

والسلام عليكم 👋🏻
👍21
خان المُبرمجين (علي فاضل)
Photo
هل من المهم أن تشارك في المشاريع مفتوحة المصدر 🤔

عندما نقلت منصة باحث من استخدام الطريقة الافتراضية لبناء واجهات المستخدم في إطار عمل Ruby on Rails وهي ERb إلى استخدام مكتبة Phlex، واجهت مشكلة بعد إطلاق الإصدار الجديد مباشرة، وهي أن زمن الاستجابة لم يكن مستقرًّا ولم أحصل على التحسينات المنتظرة فيه.

فبدأت بمحاولة فهم السبب بنفسي أولا، ولكن لم أصل إلى نتيجة واضحة، فباحث كان يستخدم Phlex بالإضافة إلى مكتبة RubyUI، وهي بديل عن مكتبة shadcn/ui ولكن للغة Ruby، فلم أجد أي مشكلة في استخدامي للمكتبتين داخل مشروع باحث.

فتوجّهت إلى مجتمع مكتبة Phlex على Discord وبدأت نقاشًا بخصوص هذا الأمر مع ذكر طريقة استخدامي للمكتبتين وصورة من لوحة متابعة زمن الاستجابة في الموقع، ولكن لم يخطر في ذهن أحد من الموجودين حلٌّ مباشر، إلا أن النصيحة كانت: "حاول استخدام Vernier لاستخراج Flame Graphs ومنها يمكن أن تبدأ في التفتيش عن السبب".

كنت قد شاهدت محاضرة عن Vernier بالفعل، وهو عبارة عن CRuby Profiler، ولكن لم أفهم كيف يمكنني قراءة الـ Frame Graphs بشكل كبير، فحاولت ولكنني سرعان ما طلبت المساعدة من خلال مشاركة ملف الـ Profile المستخرج من Vernier مع المجتمع، مع ذكر الملاحظة الوحيدة التي تمكنت من استخراجها وهي أن دالة merge من مكتبة tailwind_merge تُستخدم بكثرة وتستهلك وقتًا كبيرا.

بعد نقاش دار في المجتمع، وجدنا أن مكتبة RubyUI تستخدم مكتبة tailwind_merge لدمج الـ CSS Classes الخاصة بالمكتبة مع الـ CSS Classes المُستخدمة من قِبل المطوّر، فانتقلنا للسؤال التالي وهو: "هل يمكننا تحسين أداء هذه المكتبة؟"، وأظن أننا تسرعنا في طرح هذا السؤال.

مكتبة tailwind_merge كانت تستخدم التخزين المؤقت أو Caching، وكانت مكتوبة بطريقة جيدة ولا يمكن أن تكون هي السبب، فانتقلنا للسؤال التالي: "هل تُستخدم مكتبة tailwind_merge بطريقة صحيحة داخل مكتبة RubyUI؟"، وهنا كانت المشكلة!

صحيح أن مكتبة tailwind_merge تقوم بعمل تخزين مؤقت للنتائج عند استخدام دالة merge لكي لا تُعيد الحسابات أكثر من مرة لنفس المدخلات، ولكن هذا التخزين المؤقت على مستوى الكائن الواحد من نوع TailwindMerge::Merger، والمشكلة كانت أن مكتبة RubyUI في كل مرة تقوم بتعريف كائن جديد من نوع TailwindMerge::Merger، فلا يُستفاد من التخزين المؤقت!

بمجرد تعريف الكائن من نوع TailwindMerge::Merger كثابت في مكتبة RubyUI والبدء في إعادة استخدامه، حُلّت المشكلة ولله الحمد، ويمكنك الاطلاع على التعديل من هنا:
https://github.com/ruby-ui/ruby_ui/commit/2b770cae877e096237c324670fa9bf7fdd7d3d30

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

والسلام عليكم 👋🏻

ملاحظة: ذكرت في منشوري السابق أن زمن الاستجابة كان أفضل مع Phlex، ولكن بعد حل هذه المشكلة.
11
نفحاتٍ نبويّة قد أقبلت بالسّعد والسّرور🌿

فإنّ الأرواح قد وجدت ريح طيْبَةَ وساكنها؛ فهاجت لواعج النّفس لمجلسٍ تُتلى فيه سنّة الحبيب المصطفى ﷺ، ولعلّ أيّام الوصال قد دنت!🤍

🤍فنحن على موعدٍ نرتقبه ونعدّ له العُدّة، فقد أقبلت الدّورة العلميّة المكثّفة:
«هِمَمْ 3 - لعام ١٤٤٦ هـ»

لتجمعنا على موائد⬇️

ســـنــن الــنّــسائـيّ

◀️مع الشَّيخ إبراهيم رفيق الطَّويل

🔘من يوم السّبت 09 شعبان 1446 هـ إلى يوم الثّلاثاء 19 شعبان 1446هـ.

📌وجاهيًّا: مجمّع مكين-قرب إشارات وادي صقرة - « موقع المجمّع »

🔘توجد أماكن مُخصَّصة للنّساء.

💻كما يُمكنكم المُتابعة عبر البثّ المُباشر فيسبوك | يوتيوب

إجازة بالسّند المتّصل إلى المصنّف لمن يحضر المجالس كاملة 📚!

🔘استمارة التّسجيل بالدّورة:
https://forms.gle/4wwKAG9YDNkMjm288

🟢تكاتف أهل غراس لتغطية تكاليف الدّورات العلميّة المُكثّفة أمر ضروريّ لاستدامتها؛ لذلك نحن بانتظاركم لتغطية تكاليف أجور المكان، والتّنسيقات، وكفالة الكتب للمحتاجين، والضّيافة والإعلان.. يمكنكم التّواصل عبر البوت:
https://t.me/gherasal3elm_bot

🌐 تـابعوا قناة أكاديميّة غراس العلم للاطّلاع على كلّ جديد:
https://t.me/gherasal3elm

شاركوا الخير ودلّوا عليه، فالدّال على الخير كفاعله🌱

#همم3
#أكاديمية_غراس_العلم✔️
Please open Telegram to view this post
VIEW IN TELEGRAM
3