Vibe Coding — تطبيقك الأول دون معرفة البرمجة — 7. قاعدة البيانات: بياناتك في كل مكان

11 min read min de lecture
الفصل 07

قاعدة البيانات: بياناتك في كل مكان

الفصل 7 من 10 · 70%

أهداف هذا الفصل

  • فهم ما هي قاعدة البيانات وكيف تنتظم
  • ترحيل تطبيقك من localStorage إلى قاعدة حقيقية على الإنترنت
  • ضمان ألا يرى كل مستخدم إلا بياناته الخاصة

القطعة الناقصة

تلاميذ توم يسجلون الدخول الآن ببريدهم — لكن لينا، الوفية لموقعها، تبلّغ أن عاداتها في مركز التوثيق ما زالت غير موجودة على هاتفها. طبيعي: المصادقة تقول من الحاضر، أما البيانات فما زالت تعيش في localStorage كل جهاز. ينقص مكان مركزي تُرتَّب فيه عادات كل حساب: قاعدة بيانات على الإنترنت. هذه ورشة هذا الفصل، وهي على الأرجح الأكثر تحويلًا في الدورة — بعدها، يكف تطبيقك عن كونه لعبة متصفح ليصبح خدمة حقيقية.

تغيير المنطق يُختصر في جملة: بدل أن يحفظ كل متصفح نسخته الخاصة من البيانات، تقرأ كل الأجهزة وتكتب في المكان نفسه، خادم قاعدة بيانات. يصبح تطبيقك شبّاكًا: يعرض ما تقوله القاعدة، ويسجل فيها كل إجراء. تؤشّر لينا «القراءة» على هاتفها؛ تنطلق الإشارة إلى القاعدة؛ وفي الغد بمركز التوثيق، يسأل التطبيق القاعدة «أرني عادات لينا» فيجد كل شيء هناك.

قاعدة البيانات، عمليًا

إن سبق لك فتح جدول بيانات، فأنت تعرف 80% من المفهوم. قاعدة البيانات مجموعة جداول؛ كل جدول يشبه ورقة حساب بـأعمدة (أنواع المعلومات) وأسطر (السجلات). كل سطر يملك معرّفًا فريدًا (id)، و— هنا الجزء السحري — يمكن لسطر أن يشير إلى آخر: عمود user_id في عادة ما يقول «هذه العادة تخص هذا المستخدم». هذا ما يسمى علاقة، وهي التي تربط البيانات بنظافة بحسابات الفصل 6.

نموذج توم مينيمالي: جدول habits (سطر لكل عادة، باسمها وuser_id مالكها) وجدول checks (سطر لكل يوم مؤشَّر، مرتبط بعادته). جدولان، أربعة أعمدة مفيدة لكل منهما — قاوم إغراء التخطيط لعشرة «لوقت لاحق». لست بحاجة إلى كتابة ما يلي بنفسك، لكن اعرف قراءته: إنها لغة SQL التي سيولّدها الذكاء الاصطناعي لإنشاء الجداول.

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 فيها هو معرّفه». والقاعدة نفسها ترفض كل ما عدا ذلك، مهما فعل كود التطبيق.

بدون تفعيل RLS، يستطيع أي مستخدم متصل تقنيًا قراءة بيانات كل الآخرين — تكفي بضع مناورات في وحدة تحكم المتصفح. اشترط دائمًا، حرفيًا، في موجّهك: «فعّل الـRow Level Security بقاعدة لكل جدول: كل مستخدم لا يصل إلا إلى أسطره الخاصة». هذا غير قابل للتفاوض.

الترحيل دون فقدان شيء

مستخدموك الحاليون لديهم بيانات في localStorage: رميها يعني تحميلهم ثمن ترقيتك. خطة الترحيل كلاسيكية وأنيقة: عند أول اتصال لمستخدم، ينظر التطبيق هل بقيت بيانات محلية، ويقترح عليه استيرادها إلى حسابه. بعد استيراد ناجح، يُنظَّف localStorage، وتصبح القاعدة مصدر الحقيقة الوحيد. إليك موجّه توم الكامل — لاحظ أنه يقطّع الورشة بنفسه إلى مراحل:

PROMPT
طوّر تطبيقي لتتبع العادات من localStorage إلى Supabase.
السياق: المصادقة بالرابط السحري تعمل أصلًا (الفصل السابق).
المراحل التي أريدها، بهذا الترتيب:
1. أنشئ جدولي habits وchecks، مرتبطين بالمستخدم المتصل عبر user_id
2. فعّل الـRow Level Security بقاعدة لكل جدول: كل مستخدم لا يقرأ ولا يعدّل إلا أسطره الخاصة
3. اجعل التطبيق يقرأ ويكتب في القاعدة بدل localStorage: الإضافة، الحذف، التأشير، حساب السلسلة
4. عند أول اتصال لمستخدم ما زالت لديه بيانات محلية، اقترح عليه استيرادها إلى حسابه، ثم نظّف localStorage
نفّذ مرحلة واحدة في كل مرة وانتظر تأكيد اختباري قبل الانتقال إلى التالية.
في كل مرحلة، اشرح لي في جملتين ما فعلته.

هذا الموجّه يكثّف كل ما تعلمته: الرؤية الكاملة المعلنة منذ البداية (الفصل 3)، التقطيع إلى مراحل قابلة للاختبار (الفصل 4)، الأمان المشترط صراحة، وطلب الشرح الذي يحوّل كل مرحلة إلى درس. عندما ينهي الذكاء الاصطناعي المرحلة 1، اذهب لرؤية جداولك في لوحة تحكم Supabase (تبويب «Table Editor»): رؤية بياناتك «على الحقيقة»، في واجهة الخدمة، تجعل المفهوم كله ملموسًا.

اختبار الاستمرارية بجدية

الترحيل يمس قلب تطبيقك: يجب أن يكون الاختبار على مستواه. لا تكتفِ بـ«يبدو أنه يعمل» — نفّذ سيناريو كاملًا، بعدة حسابات وعدة أجهزة. إليك قائمة توم المرجعية:

  • الاستمرارية: أشّر عادة، أعد تحميل الصفحة، أغلق المتصفح، عُد — الإشارة ما زالت هناك.
  • تعدد الأجهزة: أشّر على هاتفك، أعد التحميل على الحاسوب — تظهر الإشارة.
  • العزل: أنشئ حسابي اختبار، أضِف عادات مختلفة في كلٍّ، وتحقق ألا يرى أيٌّ بيانات الآخر.
  • الترحيل: على متصفح فيه بيانات محلية قديمة، سجّل الدخول وتحقق أن الاستيراد يُقترح، ثم أن كل شيء وصل إلى الحساب.
  • تسجيل الخروج: عند الخروج، يجب ألا يعرض التطبيق أي بيانات.

لاختبار العزل — الأهم — استعن بالمساعدة بنشاط. الذكاء الاصطناعي ممتاز في توليد سيناريوهات اختبار أذكى من سيناريوهاتك:

PROMPT
أنشأت حسابي اختبار: eleve1@test.fr وeleve2@test.fr.
أعطني سيناريو اختبار خطوة بخطوة للتحقق من أن:
- كل حساب لا يرى إلا عاداته وإشاراته الخاصة
- إشارة على جهاز تظهر على جهاز آخر للحساب نفسه بعد إعادة التحميل
- مستخدم خارج الجلسة لا يرى أي بيانات
اشرح لي بعدها كيف أتحقق مباشرة في لوحة تحكم Supabase أن كل سطر في habits يحمل user_id الصحيح، وكيف أختبر أن الـRow Level Security يمنع فعلًا وصولًا متقاطعًا.
اعتد فتح لوحة تحكم Supabase بموازاة اختباراتك: ترى الأسطر تظهر مباشرة عندما تؤشّر في التطبيق. إنها أفضل وسيلة لفهم ما يجري «خلف الكواليس» — ولرصد فوري لسطر بـuser_id ناقص أو خاطئ.

زمن الاستجابة وحالات التحميل

تغيير خفي يرافق الترحيل: لم تعد بياناتك فورية. مع localStorage، كان كل شيء في المكان؛ ومع قاعدة على الإنترنت، كل قراءة وكل كتابة تجري ذهابًا وإيابًا عبر الشبكة لعشرات أو مئات الميلي ثانية. في الغالب لا يُلاحظ — لكن على اتصال بطيء، قائمة تستغرق ثانية للظهور دون أي مؤشر تعطي انطباع تطبيق معطل. اطلب من الذكاء الاصطناعي إضافة حالات تحميل («مؤشر صغير أثناء تحميل العادات») ورسالة واضحة عند فشل الشبكة («تعذر الوصول إلى الخادم، أعد المحاولة»).

وهي أيضًا لحظة تعلّم انعكاس محترفين: اختبار تطبيقك بمحاكاة شبكة سيئة. في أدوات تطوير المتصفح (F12)، يتيح تبويب «Network» تقييد الاتصال («Slow 3G»). ثلاثون ثانية من الاختبار في هذه الظروف تريك بالضبط ما سيعيشه مستخدموك الأسوأ اتصالًا — وما يجب تحسينه.

الباقة المجانية في Supabase تغطي بسعة تطبيقًا كتطبيق توم: 500 ميغابايت من قاعدة البيانات تعني سنوات من إشارات العادات. لا تنشغل بالحدود قبل أن يكون لديك مئات المستخدمين النشطين — ويومها، ستكون مشكلة جميلة.

ما كسبه توم للتو

قِس المسافة: لتطبيق توم الآن حسابات، وبيانات مركزية، مؤمَّنة سطرًا بسطر، ومتزامنة بين كل الأجهزة. تؤشّر لينا في مركز التوثيق، تتفقد سلسلتها في الحافلة، وكل شيء متسق. لكن ثمة مكسب أهدأ: صار لدى توم backend حقيقي. كل الميزات «المستحيلة» سابقًا — إرسال رسائل بريدية، قبول دفعة مالية، توصيل ذكاء اصطناعي — صارت متاحة، لأن لديها أخيرًا مكانًا تستند إليه. هذا بالضبط برنامج الفصل التالي.

🛠️ حان دورك

السياق

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

التعليمات

  1. صِف للذكاء الاصطناعي نموذج بياناتك بلغة عادية («جدول لـ...، جدول لـ...») واطلب منه مخطط SQL مشروحًا.
  2. أرسل موجّه الترحيل مشترطًا صراحة الـRow Level Security، مرحلة واحدة في كل مرة.
  3. بعد مرحلة الجداول، افتح لوحة تحكم Supabase وتحقق من بنيتها في الـTable Editor.
  4. نفّذ القائمة المرجعية كاملة: الاستمرارية، تعدد الأجهزة، العزل بين حسابي اختبار، ترحيل البيانات المحلية.
  5. اطلب إضافة حالات تحميل ورسالة خطأ شبكة، ثم اختبر في وضع «Slow 3G» عبر F12.
  6. commit نهائي: «ترحيل قاعدة بيانات كامل ومختبَر» — إنه معلم رئيسي في مشروعك.
تلميح — إن عرض التطبيق قائمة فارغة بعد الترحيل بينما القاعدة تحتوي أسطرًا، فالسبب دائمًا تقريبًا الـRLS التي تمنع (قاعدة ناقصة أو مكتوبة بشكل خاطئ). أعطِ الذكاء الاصطناعي رسالة الخطأ من وحدة التحكم وقاعدة RLS الحالية: التشخيص فوري.

باختصار

  • قاعدة البيانات على الإنترنت هي المكان المركزي حيث تقرأ كل الأجهزة وتكتب البيانات نفسها.
  • جداول، أعمدة، أسطر: القاعدة تشبه جدول بيانات، بمعرّفات فريدة وعلاقات.
  • عمود user_id يربط كل بيانات بمالكها — إنه الجسر مع مصادقة الفصل 6.
  • الـRow Level Security غير قابلة للتفاوض: بدونها، يستطيع كل مستخدم تقنيًا قراءة بيانات الآخرين.
  • رحّل دون خسارة: اقترح استيراد البيانات المحلية عند أول اتصال، ثم نظّف localStorage.
  • اختبر بجدية: الاستمرارية، تعدد الأجهزة، العزل بين الحسابات، والسلوك على شبكة بطيئة.
  • مع backend حقيقي، تصبح الميزات المتقدمة (البريد، الدفع، الذكاء الاصطناعي) متاحة أخيرًا.

اختبار — تحقّق من فهمك

1. أي مشكلة تحلها قاعدة البيانات ولم تكن المصادقة وحدها تحلها؟

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

2. ما وظيفة عمود user_id في جدول habits؟

user_id يشير إلى المستخدم المالك: إنها العلاقة التي تتيح عرض عادات كلٍّ له، وللـRLS منع الآخرين.

3. ماذا يحدث إن نسيت تفعيل الـRow Level Security؟

افتراضيًا، لا شيء يعزل الأسطر بين المستخدمين. الـRLS تجعل القاعدة نفسها تطبّق «لكلٍّ أسطره» — اشترطها حرفيًا في موجّهك.

4. كيف ترحّل بيانات localStorage للمستخدمين الحاليين دون فقدانها؟

الاستيراد عند أول اتصال يحفظ تاريخ كلٍّ: تصبح القاعدة بعدها مصدر الحقيقة الوحيد. مستخدموك لا يدفعون ثمن ترقيتك.

5. بعد الترحيل، تظهر القائمة فارغة بينما القاعدة تحتوي أسطرًا فعلًا. ما السبب الأرجح؟

إنه العرَض الكلاسيكي: القاعدة ترفض القراءة لأن قاعدة الـRLS لا تتعرف على المستخدم. وحدة التحكم + قاعدة RLS مرسلتان إلى الذكاء الاصطناعي = تشخيص فوري.

Auteur(s)

R

REHOUMA Haythem

Haythem Rehouma est un ingénieur et architecte IA et cloud, formateur et enseignant technique, avec un profil orienté IA médicale, AWS, MLOps, LLM/RAG et vision par ordinateur.