قاعدة البيانات: بياناتك في كل مكان
أهداف هذا الفصل
- فهم ما هي قاعدة البيانات وكيف تنتظم
- ترحيل تطبيقك من localStorage إلى قاعدة حقيقية على الإنترنت
- ضمان ألا يرى كل مستخدم إلا بياناته الخاصة
القطعة الناقصة
تلاميذ توم يسجلون الدخول الآن ببريدهم — لكن لينا، الوفية لموقعها، تبلّغ أن عاداتها في مركز التوثيق ما زالت غير موجودة على هاتفها. طبيعي: المصادقة تقول من الحاضر، أما البيانات فما زالت تعيش في localStorage كل جهاز. ينقص مكان مركزي تُرتَّب فيه عادات كل حساب: قاعدة بيانات على الإنترنت. هذه ورشة هذا الفصل، وهي على الأرجح الأكثر تحويلًا في الدورة — بعدها، يكف تطبيقك عن كونه لعبة متصفح ليصبح خدمة حقيقية.
تغيير المنطق يُختصر في جملة: بدل أن يحفظ كل متصفح نسخته الخاصة من البيانات، تقرأ كل الأجهزة وتكتب في المكان نفسه، خادم قاعدة بيانات. يصبح تطبيقك شبّاكًا: يعرض ما تقوله القاعدة، ويسجل فيها كل إجراء. تؤشّر لينا «القراءة» على هاتفها؛ تنطلق الإشارة إلى القاعدة؛ وفي الغد بمركز التوثيق، يسأل التطبيق القاعدة «أرني عادات لينا» فيجد كل شيء هناك.
قاعدة البيانات، عمليًا
إن سبق لك فتح جدول بيانات، فأنت تعرف 80% من المفهوم. قاعدة البيانات مجموعة جداول؛ كل جدول يشبه ورقة حساب بـأعمدة (أنواع المعلومات) وأسطر (السجلات). كل سطر يملك معرّفًا فريدًا (id)، و— هنا الجزء السحري — يمكن لسطر أن يشير إلى آخر: عمود user_id في عادة ما يقول «هذه العادة تخص هذا المستخدم». هذا ما يسمى علاقة، وهي التي تربط البيانات بنظافة بحسابات الفصل 6.
نموذج توم مينيمالي: جدول habits (سطر لكل عادة، باسمها وuser_id مالكها) وجدول checks (سطر لكل يوم مؤشَّر، مرتبط بعادته). جدولان، أربعة أعمدة مفيدة لكل منهما — قاوم إغراء التخطيط لعشرة «لوقت لاحق». لست بحاجة إلى كتابة ما يلي بنفسك، لكن اعرف قراءته: إنها لغة SQL التي سيولّدها الذكاء الاصطناعي لإنشاء الجداول.
create table habits ( id uuid primary key default gen_random_uuid(), user_id uuid references auth.users not null, name text not null, created_at timestamptz default now() ); create table checks ( id uuid primary key default gen_random_uuid(), habit_id uuid references habits not null, day date not null );
اقرأه كأنه شبه لغة عادية: «أنشئ جدول habits؛ لكل سطر معرّف فريد، يخص مستخدمًا، يحمل اسمًا، ويحفظ تاريخ إنشائه». السطر references auth.users هو العلاقة: يستحيل إنشاء عادة يتيمة، بلا مالك. اطلب دائمًا من الذكاء الاصطناعي شرح المخطط الذي يقترحه — ففي هذه القراءات المشروحة تتعلم أكثر ما تتعلم.
flowchart LR T["هاتف لينا"] -->|"تؤشّر عادة"| B["قاعدة بيانات Supabase"] O["حاسوب مركز التوثيق"] -->|"الحساب نفسه"| B B -->|"يعيد البيانات نفسها"| T B -->|"يعيد البيانات نفسها"| O
الأمان أولًا: كلٌّ يرى بياناته
سؤال حاسم قبل كتابة أي بيانات: ما الذي يمنع تطبيق لينا من قراءة عادات كريم؟ الجواب: لا شيء، افتراضيًا. عليك أنت فرض ذلك، عبر ما يسميه Supabase الـRow Level Security (RLS) — «الأمان على مستوى الأسطر». المبدأ صافٍ: كل جدول يتلقى قاعدة من نوع «لا يستطيع المستخدم قراءة وتعديل إلا الأسطر التي user_id فيها هو معرّفه». والقاعدة نفسها ترفض كل ما عدا ذلك، مهما فعل كود التطبيق.
الترحيل دون فقدان شيء
مستخدموك الحاليون لديهم بيانات في localStorage: رميها يعني تحميلهم ثمن ترقيتك. خطة الترحيل كلاسيكية وأنيقة: عند أول اتصال لمستخدم، ينظر التطبيق هل بقيت بيانات محلية، ويقترح عليه استيرادها إلى حسابه. بعد استيراد ناجح، يُنظَّف localStorage، وتصبح القاعدة مصدر الحقيقة الوحيد. إليك موجّه توم الكامل — لاحظ أنه يقطّع الورشة بنفسه إلى مراحل:
طوّر تطبيقي لتتبع العادات من localStorage إلى Supabase. السياق: المصادقة بالرابط السحري تعمل أصلًا (الفصل السابق). المراحل التي أريدها، بهذا الترتيب: 1. أنشئ جدولي habits وchecks، مرتبطين بالمستخدم المتصل عبر user_id 2. فعّل الـRow Level Security بقاعدة لكل جدول: كل مستخدم لا يقرأ ولا يعدّل إلا أسطره الخاصة 3. اجعل التطبيق يقرأ ويكتب في القاعدة بدل localStorage: الإضافة، الحذف، التأشير، حساب السلسلة 4. عند أول اتصال لمستخدم ما زالت لديه بيانات محلية، اقترح عليه استيرادها إلى حسابه، ثم نظّف localStorage نفّذ مرحلة واحدة في كل مرة وانتظر تأكيد اختباري قبل الانتقال إلى التالية. في كل مرحلة، اشرح لي في جملتين ما فعلته.
هذا الموجّه يكثّف كل ما تعلمته: الرؤية الكاملة المعلنة منذ البداية (الفصل 3)، التقطيع إلى مراحل قابلة للاختبار (الفصل 4)، الأمان المشترط صراحة، وطلب الشرح الذي يحوّل كل مرحلة إلى درس. عندما ينهي الذكاء الاصطناعي المرحلة 1، اذهب لرؤية جداولك في لوحة تحكم Supabase (تبويب «Table Editor»): رؤية بياناتك «على الحقيقة»، في واجهة الخدمة، تجعل المفهوم كله ملموسًا.
اختبار الاستمرارية بجدية
الترحيل يمس قلب تطبيقك: يجب أن يكون الاختبار على مستواه. لا تكتفِ بـ«يبدو أنه يعمل» — نفّذ سيناريو كاملًا، بعدة حسابات وعدة أجهزة. إليك قائمة توم المرجعية:
- الاستمرارية: أشّر عادة، أعد تحميل الصفحة، أغلق المتصفح، عُد — الإشارة ما زالت هناك.
- تعدد الأجهزة: أشّر على هاتفك، أعد التحميل على الحاسوب — تظهر الإشارة.
- العزل: أنشئ حسابي اختبار، أضِف عادات مختلفة في كلٍّ، وتحقق ألا يرى أيٌّ بيانات الآخر.
- الترحيل: على متصفح فيه بيانات محلية قديمة، سجّل الدخول وتحقق أن الاستيراد يُقترح، ثم أن كل شيء وصل إلى الحساب.
- تسجيل الخروج: عند الخروج، يجب ألا يعرض التطبيق أي بيانات.
لاختبار العزل — الأهم — استعن بالمساعدة بنشاط. الذكاء الاصطناعي ممتاز في توليد سيناريوهات اختبار أذكى من سيناريوهاتك:
أنشأت حسابي اختبار: eleve1@test.fr وeleve2@test.fr. أعطني سيناريو اختبار خطوة بخطوة للتحقق من أن: - كل حساب لا يرى إلا عاداته وإشاراته الخاصة - إشارة على جهاز تظهر على جهاز آخر للحساب نفسه بعد إعادة التحميل - مستخدم خارج الجلسة لا يرى أي بيانات اشرح لي بعدها كيف أتحقق مباشرة في لوحة تحكم Supabase أن كل سطر في habits يحمل user_id الصحيح، وكيف أختبر أن الـRow Level Security يمنع فعلًا وصولًا متقاطعًا.
زمن الاستجابة وحالات التحميل
تغيير خفي يرافق الترحيل: لم تعد بياناتك فورية. مع localStorage، كان كل شيء في المكان؛ ومع قاعدة على الإنترنت، كل قراءة وكل كتابة تجري ذهابًا وإيابًا عبر الشبكة لعشرات أو مئات الميلي ثانية. في الغالب لا يُلاحظ — لكن على اتصال بطيء، قائمة تستغرق ثانية للظهور دون أي مؤشر تعطي انطباع تطبيق معطل. اطلب من الذكاء الاصطناعي إضافة حالات تحميل («مؤشر صغير أثناء تحميل العادات») ورسالة واضحة عند فشل الشبكة («تعذر الوصول إلى الخادم، أعد المحاولة»).
وهي أيضًا لحظة تعلّم انعكاس محترفين: اختبار تطبيقك بمحاكاة شبكة سيئة. في أدوات تطوير المتصفح (F12)، يتيح تبويب «Network» تقييد الاتصال («Slow 3G»). ثلاثون ثانية من الاختبار في هذه الظروف تريك بالضبط ما سيعيشه مستخدموك الأسوأ اتصالًا — وما يجب تحسينه.
ما كسبه توم للتو
قِس المسافة: لتطبيق توم الآن حسابات، وبيانات مركزية، مؤمَّنة سطرًا بسطر، ومتزامنة بين كل الأجهزة. تؤشّر لينا في مركز التوثيق، تتفقد سلسلتها في الحافلة، وكل شيء متسق. لكن ثمة مكسب أهدأ: صار لدى توم backend حقيقي. كل الميزات «المستحيلة» سابقًا — إرسال رسائل بريدية، قبول دفعة مالية، توصيل ذكاء اصطناعي — صارت متاحة، لأن لديها أخيرًا مكانًا تستند إليه. هذا بالضبط برنامج الفصل التالي.
السياق
يكرّس توم نهاية أسبوعه للترحيل: إنها الورشة الأكثر بنيوية منذ بداية المشروع، ويريد إنجازها بنظافة — جداول، أمان، ترحيل البيانات الموجودة، اختبارات متعددة الحسابات. اسلك المسار نفسه على تطبيقك، خطوة بخطوة، دون التقدم أبدًا قبل المصادقة على المرحلة الجارية. في النهاية، ستتبعك بياناتك في كل مكان.
التعليمات
- صِف للذكاء الاصطناعي نموذج بياناتك بلغة عادية («جدول لـ...، جدول لـ...») واطلب منه مخطط SQL مشروحًا.
- أرسل موجّه الترحيل مشترطًا صراحة الـRow Level Security، مرحلة واحدة في كل مرة.
- بعد مرحلة الجداول، افتح لوحة تحكم Supabase وتحقق من بنيتها في الـTable Editor.
- نفّذ القائمة المرجعية كاملة: الاستمرارية، تعدد الأجهزة، العزل بين حسابي اختبار، ترحيل البيانات المحلية.
- اطلب إضافة حالات تحميل ورسالة خطأ شبكة، ثم اختبر في وضع «Slow 3G» عبر F12.
- commit نهائي: «ترحيل قاعدة بيانات كامل ومختبَر» — إنه معلم رئيسي في مشروعك.
باختصار
- قاعدة البيانات على الإنترنت هي المكان المركزي حيث تقرأ كل الأجهزة وتكتب البيانات نفسها.
- جداول، أعمدة، أسطر: القاعدة تشبه جدول بيانات، بمعرّفات فريدة وعلاقات.
- عمود user_id يربط كل بيانات بمالكها — إنه الجسر مع مصادقة الفصل 6.
- الـRow Level Security غير قابلة للتفاوض: بدونها، يستطيع كل مستخدم تقنيًا قراءة بيانات الآخرين.
- رحّل دون خسارة: اقترح استيراد البيانات المحلية عند أول اتصال، ثم نظّف localStorage.
- اختبر بجدية: الاستمرارية، تعدد الأجهزة، العزل بين الحسابات، والسلوك على شبكة بطيئة.
- مع backend حقيقي، تصبح الميزات المتقدمة (البريد، الدفع، الذكاء الاصطناعي) متاحة أخيرًا.
اختبار — تحقّق من فهمك
1. أي مشكلة تحلها قاعدة البيانات ولم تكن المصادقة وحدها تحلها؟
2. ما وظيفة عمود user_id في جدول habits؟
3. ماذا يحدث إن نسيت تفعيل الـRow Level Security؟
4. كيف ترحّل بيانات localStorage للمستخدمين الحاليين دون فقدانها؟
5. بعد الترحيل، تظهر القائمة فارغة بينما القاعدة تحتوي أسطرًا فعلًا. ما السبب الأرجح؟