ما ستتعلمه
في هذا المعمل تبني سجل تعلم صغيرًا وتحفظه باستخدام Gammal Tech، ثم تشرح بدقة ما يتغير عند حفظ كائن جديد. ستتدرب على حدود البيانات وفحص أنواعها، وتفصل بين تفضيلات يغيرها المستخدم وقرار صلاحية موثوق. الناتج سجل وهمي تمت مراجعته وورقة أدلة، وليس نظام صلاحيات جاهزًا للاستخدام التجاري.
جهز بيئة تعلم لديك تصريح باستخدامها
استخدم مشروعًا تملكه ودومين HTTPS مسجلًا له وحسابك الشخصي الموثق. أكمل تمرين المشروع الأول وتسجيل الدخول قبل تنفيذ طلبات التخزين. إذا كنت تنتظر التحقق من الحساب، أنجز تصميم البيانات وتوقع النتائج دون اتصال. لا تنشئ حسابًا شخصيًا ثانيًا ولا تستعر بيانات دخول عميل.
حمّل SDK الموثق قبل كود التمرين:
<script src="https://api.gammal.tech/sdk-web.js"></script>بعد إكمال الدخول بالطريقة المدعومة، أضف العناصر التالية وضع JavaScript الخاص بالتمرين بعدها:
<button id="run-data-lab" type="button">Run fictional data lab</button>
<pre id="lab-result"></pre>
<p id="lab-status" role="status"></p>استخدم قيمًا وهمية داخل حقل learningLab لا يحتوي على عمل سابق، لأن التمارين ستستبدله. يبدأ الطلب بضغط مقصود على الزر.
صمم سجلًا صغيرًا قبل إرسال أي طلب
يوضح عقد التكامل المنشور وجود كائن JSON واحد لكل مستخدم داخل كل مشروع بحد 1 MB. تعيد user.get() كائنًا فارغًا عند عدم وجود بيانات. المفاتيح التي تبدأ بـ _gt_ محجوزة ومرفوضة.
ابدأ بالشكل الوهمي التالي:
{
"learningLab": {
"language": "en",
"progress": { "lesson": 1, "completed": false }
},
"learningMarker": "round-1"
}اللغة اختيار من قائمة محددة، ورقم الدرس عدد صحيح بين 1 و20، وإتمام الدرس قيمة منطقية. العلامة تساعدنا في ملاحظة سلوك المستوى الأعلى. لا تمنح أي قيمة هنا حق دخول دورة مدفوعة. اكتب معنى كل حقل ونوعه المقبول في ورقة العمل.
أعد بناء الحقول المعروفة فقط
للبيانات الناقصة أو القديمة، تنشئ الدالة كائنًا بالحقول المعروفة فقط:
function normalizeLab(value) {
const object = x => x !== null && typeof x === "object"
&& !Array.isArray(x);
const item = object(value) ? value : {};
const progress = object(item.progress) ? item.progress : {};
return {
language: ["en", "ar"].includes(item.language)
? item.language : "en",
progress: {
lesson: Number.isInteger(progress.lesson)
&& progress.lesson >= 1 && progress.lesson <= 20
? progress.lesson : 1,
completed: typeof progress.completed === "boolean"
? progress.completed : false
}
};
}اختبرها محليًا مع null ومصفوفة وكائن ينقصه التقدم ورقم درس مكتوب كنص، ومع completed: "false". النص ليس القيمة المنطقية false؛ اعتبار كل نص غير فارغ صحيحًا ينتج سلوكًا خاطئًا. المفاتيح غير المعروفة لا تُنسخ إلى الناتج.
هذه المعالجة توفر قيمًا افتراضية مناسبة للتطبيق، لكنها لا تثبت صحة السجل الأصلي أو صلاحية المستخدم. وعند ملء نموذج، اعرض رسالة للقيمة غير المقبولة بدلًا من تغييرها بصمت وإخبار المستخدم أنك حفظت اختياره كما هو.
توقع الدمج والاستبدال قبل تنفيذ المثال
تدمج Gammal Tech المفاتيح المرسلة في المستوى الأعلى، لكنها تستبدل الكائن المتداخل الذي ترسله عند مفتاح معين. لذلك سيستبدل الحفظ الثاني كائن learningLab بالكامل. اكتب توقعك أولًا:
const dataLabButton = document.getElementById("run-data-lab");
const dataLabResult = document.getElementById("lab-result");
const dataLabStatus = document.getElementById("lab-status");
dataLabButton.addEventListener("click", async () => {
if (dataLabButton.disabled) return;
dataLabButton.disabled = true;
try {
await GammalTech.user.save({
learningLab: {
language: "en", progress: { lesson: 1, completed: false }
},
learningMarker: "round-1"
});
await GammalTech.user.save({ learningLab: { language: "ar" } });
const saved = await GammalTech.user.get();
dataLabResult.textContent = JSON.stringify({
learningLab: saved.learningLab,
learningMarker: saved.learningMarker
}, null, 2);
dataLabStatus.textContent = "Read-back complete.";
} catch {
dataLabStatus.textContent = "Result not confirmed. Check before retrying.";
} finally {
dataLabButton.disabled = false;
}
});القراءة المتوقعة تحتوي على العلامة round-1 وعلى learningLab: {"language":"ar"}. حقول التقدم السابقة لم تعد موجودة. الخطأ الشائع هو توقع دمج عميق يحافظ عليها. اعرض حقول التمرين الوهمية فقط، ولا تنسخ بقية بيانات المستخدم إلى المخرجات. وإذا تعذر تأكيد الطلب، افحص الحالة قبل المحاولة مجددًا بدلًا من افتراض أن شيئًا لم يحدث.
نفذ استبدالًا مقصودًا وافهم التعديل المتزامن
لتغيير رقم الدرس مع الاحتفاظ بالتفضيلات المعروفة، اقرأ السجل وأعد بناء كائن التعلم ثم احفظه كاملًا. استبدل محتوى كتلة try السابقة بهذا الجزء، واحتفظ بمعالجة الخطأ وحالة الزر:
// Same handler context; normalizeLab is defined above.
const current = await GammalTech.user.get();
const next = normalizeLab(current.learningLab);
next.progress.lesson = 2;
await GammalTech.user.save({ learningLab: next });
const checked = await GammalTech.user.get();
dataLabResult.textContent = JSON.stringify(
normalizeLab(checked.learningLab), null, 2
);المتوقع لغة عربية ودرس رقم 2 وإتمام بقيمة افتراضية غير مكتملة، لأن التمرين السابق أزال حقول التقدم. اشرح سبب ظهور القيمة الافتراضية. انتظار انتهاء save لا يوفر شكل قراءة موثقًا، لذلك نسترجع البيانات صراحة.
هذه الخطوات ليست معاملة ذرية تمنع التعارض. قد يقرأ تبويبان حالة قديمة ثم يكتب أحدهما فوق تعديل الآخر. استخدم تبويبًا واحدًا لهذا المعمل. إذا احتاج تطبيق عميل إلى تعديلات متزامنة، حدد قواعد التعارض وتحقق من قدرة البنية المختارة على تنفيذها.
اختبر الفصل بين شخصين بموافقتهما
- اطلب من متعلم آخر لديه تصريح استخدام حسابه الشخصي الموثق على المشروع نفسه. يحتفظ كل شخص بالتحكم في دخوله.
- يحفظ كل شخص علامة وهمية مختلفة ويسجل القيمة التي يتوقعها.
- يقرأ كل منهما بالطريقة العادية ويتأكد أن علامته هي التي تظهر.
- بعد الخروج والدخول بالمسار المدعوم، كررا القراءة دون تبادل توكنات أو بيانات اعتماد.
إذا كنت تتعلم وحدك، سجل الاختبار «لم ينفذ». لا تخترع حسابًا إضافيًا ولا تعتبره ناجحًا دون تجربة. هذه مراجعة قبول وظيفية محدودة، وليست اختبار اختراق أو إثباتًا شاملًا لجميع ضوابط عزل البيانات.
سلّم السجل وورقة أدلة واضحة
سلّم تعريف الحقول والدالة وتوقعات الدمج والنتائج الفعلية وحالة اختبار الشخصين. أضف القيمة الافتراضية لكل مدخل غير سليم وجملة تشرح مشكلة التعديل من تبويبين. إن استخدمت صورًا، فاعرض فقط بيانات التمرين الوهمية دون أدوات المطور أو قيم الجلسة أو معلومات الهوية.
القبول يتطلب أنواعًا صحيحة واستبدالًا مفهومًا ورسالة خطأ محايدة وعدم منح صلاحية من السجل. حدد أيضًا من يملك حساب الدومين والنشر. تستمر مسؤولية حماية الواجهة والاستضافة والأجهزة وقواعد العمل.
أسئلة شائعة
هل أنشئ حسابًا ثانيًا لاختبار الفصل؟
استخدم حسابًا فرديًا موثقًا واحدًا لكل شخص. شارك متعلمًا آخر موافقًا ومصرحًا له بحسابه الخاص، أو سجل اختبار الشخصين على أنه لم ينفذ.
هل حفظ جزء من كائن متداخل يبقي بقية الحقول؟
لا. الدمج يخص مفاتيح المستوى الأعلى، بينما الكائن المتداخل المرسل يُستبدل. أعد بناء الكائن المطلوب وفكر في التعديلات المتزامنة قبل حفظه.
مراجع الدرس
تمت مراجعة التوثيق في 12 أكتوبر 2026. راجع التوثيق الحالي قبل تنفيذ مشروع عميل أو تحديد أسعاره.