اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'مرشحات'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 4 نتائج

  1. سنتعلم في هذا الدرس كيفية تغيير حالة الطقس في صورة بإضافة أمطار غزيرة إليها، وسنختار صورة شارع مظلم لتعطي المشهد طابعًا دراميًا، وسنزيد أولًا من انعكاسات الضوء الرقيقة على الرصيف لتحاكي مظهر الأرض المبللة بالمطر، ثم نضيف ثلاث طبقات من قطرات المطر يختلف حجم كل منها عن الأخرى لتوهم الناظر أن مشهد المطر ممتد على عمق الصورة. والصورة التي سأعمل عليها يمكنك تحميلها من هنا، وقد اخترت الخلفية المظلمة في تلك الصورة لتبرز قطرات المطر أكثر، كما أن لقطات الشوارع المظلمة تعطي نتائج رائعة إذ تحول الصورة العادية إلى لقطة درامية ممتازة. افتح الصورة في فوتوشوب، سنغيّر مظهر الأرضية أولًا لتبدو مبللة كي تضفي مزيدًا من الواقعية على المشهد. اذهب إلى قائمة Select ثم Color Range، واختر Highlights من نوع التحديد Selection Method كما بالصورة أعلاه. حرك مؤشرات Fuzziness وRange بينما تراقب المعاينة الحية للصورة حتى تحصل على مستوى مناسب للمناطق الساطعة "highlights” في الصورة ، لاحظ أن شدة الإضاءة في تلك المناطق ستحدد مدى البلل الذي سيبدو عليه الطريق. أنشئ طبقة جديدة واملأ المناطق الساطعة باستخدام اختصار ctrl+Backspace، ثم اضغط ctrl+d لتزيل التحديد. غيّر وضع الدمج "Blending mode" للطبقة البيضاء إلى Color Dodge، ثم قلّل ملء الطبقة "Fill" إلى نحو 50%. إن لم تكن راضيًا عن النتيجة فيمكنك تغيير إعدادات الملء والشفافية حتى تصل إلى اللمعان المناسب للأسفلت. ورغم أننا نحتاج المناطق الساطعة كي تعطي الطريق مظهرًا لامعًا من أثر انعكاس الضوء على ماء المطر، إلا أننا لا نريد أن تزيد شدة الضوء في باقي المناطق الساطعة سوى الطريق أكثر من اللازم، ولتحقيق ذلك، أضف قناعًا لهذه الطبقة "Layer Mask" ثم امسح المناطق التي لا نريدها بفرشاة ناعمة، كما بالصورة أعلاه. أضف طبقة جديدة واملأها باللون الأسود باستخدام اختصار Alt+Backspace، ثم اذهب إلى Filter ثم Noise، ومنها Add Noise. غيّر قيمة Amount إلى 100%، واضبط التوزيع "Distribution" على Gaussian، وفعّل خيار Monochromatic. والآن، اذهب إلى قائمة Filter، ثم Blur، ومنها Motion Blur. اضبط الزاوية على 60 درجة مثلًا، والمسافة "Distance" على 25 بكسل. ستجد شريطًا رفيعًا على حواف الطبقة لم يُطبّق عليه تأثير motion blur، اضغط ctrl+t وزِد حجم الطبقة لتغطي هذا الشريط. غير وضع الدمج "Blending Mode" إلى Screen كي نُظهر الأجزاء البيضاء فقط من الضوضاء "Noise" التي أنشأناها، هذا يسمح للصورة الأصلية أن تظهر أيضًا من خلال قطرات المطر. اذهب إلى Image ثم Adjustments ثم Levels -أو استخدم اختصار ctrl+L- واسحب مؤشر Shadows إلى اليمين لتقليل عدد قطرات المطر. أضف طبقة جديدة واملأها بالأسود، ثم أضف فلتر Noise بقيمة 100% مع خيارات Gaussian وMonochromatic كما في المرة السابقة، ثم أضف فلتر Motion Blur. وفي إعدادات هذه الطبقة الثانية من المطر، زد المسافة Distance إلى 50 بكسل، لكن أبق الزاوية كما هي 60 درجة. أيضًا كما في المرة السابقة، اضغط ctrl+t لتزيد مساحة هذه الطبقة لتكون أكبر قليلًا من طبقة المطر الأولى كي يزيد حجم قطرات المطر، واضبط وضع الدمج "Blending Mode" على Screen. استخدم اختصار ctrl+L مرة أخرى لتفتح نافذة Levels، واسحب مؤشر Shadows إلى اليمين، ومؤشر Midtones إلى اليسار، وأبق عينك على المعاينة الحية للصورة كي تضبط الصورة على توازن مناسب بين التفرّق والكثافة الشديدة. أضف طبقة Noise ثالثة، ثم فلتر Motion Blur، لكن هذه المرة سنزيد Distance إلى 100 بكسل، وستكون هذه الطبقة لقطرات المطر القريبة التي يجب أن تبدو وكأنها تتحرك أسرع مما وراءها. زد مساحة هذه الطبقة بشكل كبير باستخدام اختصار ctrl+t لإنشاء قطرات مطر كبيرة، واضبط Blending Mode على Screen. يجب أن تضفي هذه الطبقات الثلاث التي أنشأناها عمقًا لوابل المطر الذي يهطل على الشارع الآن. قلّل كمية المطر المرئية في الطبقة الأخيرة الأمامية بالتعديل في المستويات Levels: حرك مؤشر Shadows إلى اليمين، وزد قيمة التباين Contrast بسحب midtones وhighlights إلى اليسار. في هذه الخطوة سنغير من الشكل الموحد لطبقات المطر كي تبدو عشوائية وواقعية: أضف Layer mask لكل طبقة من طبقات المطر، واستخدم فرشاة ناعمة بشفافية 50%، وانقر نقرات رقيقة بعشوائية هنا وهناك. تأكد من تطبيق هذه الخطوة لطبقات الأقنعة الأخرى لمسح أجزاء من طبقات المطر بعشوائية كي يتحقق التأثير الذي نريده، وإن أردت التراجع عن إخفاء جزء ما رأيت أن المطر قد اختفي فيه، غيّر لون الفرشاة إلى الأبيض وانقر في هذا الجزء لاسترجاع قطرات المطر. وكما ترى الآن فإن للصورة الجديدة طابعًا دراميًا يظهر جليًا فيها، كما تضفي طبقات المطر المتراكبة عمقًا لزخّات المطر التي يفترض أنها تهطل على المشهد، ثم تترك الأرض لامعة من أثر الماء المتساقط عليها. ترجمة -بتصرف- لمقال How To Add Heavy Rain to an Image in Adobe Photoshop لصاحبه Chris Spooner
  2. هل تحاول متابعة آخر التحديثات لعدِّة مشاريع على GitHub؟ إذًا أنت لست حديث العهد باستقبال العديد من الإشعارات حول: التبليغ عن العلل، ونشر تعليقات، وقبول طلبات إضافة (pull requests). تتطلب بعض الأمور السابقة تدخلًا منك، وعليك أن تعلم عن بعضها الآخر، والباقي مجرد ضوضاء. هذه مُرشِّحات (filters) لبريد Gmail التي أستعملها لكي أحصل على الإشعارات المفيدة بسرعة. لدى GitHub مركز إشعارات خاص به يسمح بترشيح الإشعارات لكل مشروع، بالإضافة إلى إظهار الإشعارات للأشياء التي تُشارِك فيها فقط. وكل إشعار له أيقونة خاصة به تُحدِّد ما إن كان مشكلةً أو طلبَ دمجٍ وسواءً بقي مفتوحًا/أو لم يُدمَج بعد. هذا مفيدٌ حقًا، ويقلل الوقت اللازم لتفقد اللائحة كل يوم؛ على سبيل المثال، ربما تريد تخطي المشكلات التي تم إغلاقها أو الطلبات التي تم دمجها، وتتطلع بسرعة على المشكلات التي لم تُذكَر فيها، وتُركِّز على ما أنت مشاركٌ فيه. ماذا لو كنت تفضل التعامل مع الإشعارات عبر البريد الإلكتروني؟ أنا أفضل أن يكون كل شيءٍ موجودًا في مكانٍ واحد في صندوق الوارد. لكني سأفوت على نفسي كل الميزات الموفرة للوقت التي يعطيني إياها مركز الإشعارات. لن يكون المرور على الإشعارات واحدًا واحدًا ذا إنتاجيةٍ عالية. لكن لحسن الحظ، يمكن جلب بعض ميزات مركز الإشعارات إلى بريدك الإلكتروني باستعمال "المرشحات" (filters)، وهذه هي المرشحات التي أستعملها مع Gmail. وسم جميع الإشعارات من GitHub لأنني أستقبل عددًا كبيرًا من الرسائل من GitHub، فأحب أن أوسمها (tag) جميعًا كي أميز بينها وبين الرسائل الأخرى بسهولة؛ ومن النادر أن تكون إشعارات GitHub ذات أولويةً عالية، ووسمها كلها سيسمح لي بإخفائها بسهولة كي أتأكد أنني لم أفوِّت رسالةً مهمةً. لضبط ما سبق، رشِّح حقل "From:‎" للبريد "notifications@github.com"، يبدو هذا في Gmail كالآتي: from:(notifications@github.com) التكليفات أحاول أن أهتم بما أنا مكلفٌ به، ولهذا أعلِّم تلك الرسائل بوسم "Assignment"، وعندما أكون مشغولًا، أنظر إلى هذه القائمة فقط لكي أتأكد أنَّ كل شيءٍ أنا مسؤولٌ عن إنجازه قد أُنجِز. عندما يُسنِد أحدهم مشكلةٍ إليك، فسيُرسِل GitHub تنبيهًا، ويمكن تعليم (أو توسيم) كامل الموضوع (thread) كتكليفٍ إليك عبر مطابقة هذه الرسالة التنبيهية. سيبدو مُرشِّح Gmail كالآتي (ابحث عن معرفك@ Assigned to): from:(notifications@github.com) Assigned to @pazdera هنالك بعض المحدوديات لهذه الطريقة لسوء الحظ، فلن يُرسَل إليك إشعارٌ إن أسندتَ المشكلة إلى نفسك ولن يُوسَّم الموضوع بشكلٍ صحيح في هذه الحالة؛ وإن أعيد إسناد المشكلة إلى شخصٍ آخر، فسيبقى الموضوع موسمًا على أنك مكلّف بالمشكلة. ذكر معرفك (Mentions) ربما هذا المرشح هو أكثرهم فائدةً لأنه يسمح لك برؤية الرسائل التي ذُكِرتَ فيها دون الحاجة إلى النظر إلى جميع الرسائل غير المهمة بحثًا عن مُعرِّفك على GitHub، فستعلم تمامًا أين طُلِبَت مداخلتك. استعمل مُرشِّحًا يطابق مُعرِّفك على GitHub في جسد الرسالة كما يلي: from:(notifications@github.com) @pazdera طلب pull request تم دمجه Merged لن تكون -في أغلب الأوقات- هنالك حاجةٌ لمداخلتك عندما يُدمج طلب Pull Request ويمكنك تجاوزها في أغلب الأحيان (خصيصًا إن لم تُذكَر في النقاش في طلب Pull Request ‏[PR]). يُرسِل GitHub إشعارًا يمكِّنك من إنشاء مُرشِّح لتوسيم الموضوع (thread) على أنه Merged. from:(notifications@github.com) Merged للأسف، لا يوجد دعم للتعابير النمطية (regular expressions) في Gmail، ولهذا سيُطابِق المرشح السابق التعليقات التي يذكر فيها صاحبها الكلمة "Merged". لكن -وإن كان يبدو ذلك مشكلةً كبيرةً- من النادر حدوث ذلك حسب تجربتي. مشكلة تم إغلاقها Closed في نهاية المطاف، من المفيد -عندما تُغلق مشكلة- أن تعرف عن ذلك دون الحاجة إلى النقر على الرسالة لفتحها. أستعمل المُرشِّح الآتي لتعليم كل تلك الرسائل للحذف مباشرةً. from:(notifications@github.com) Closed \# هذه هي المرشحات الخمسة التي تساعدني في التخلص من الكم الكبير من تنبيهات GitHub في بريدي. ما الذي تستعمله كيلا تقضي ساعاتٍ في بريدك؟ شارك ذلك في التعليقات أدناه. ترجمة -وبتصرّف- للمقال ‎5 Useful Gmail Filters for GitHub Users لصاحبه Radek Pazdera.
  3. يمكننا الآن، بعد إكمال إعداد بيئة الإنتاج في الدرس السابق، البدء في إعداد نظام مركزي للسجلات؛ وهو وسيلة رائعة لجمع سجلات الخواديم ومعاينتها. لا يعدّ إعداد نظام سجلات دقيق، على العموم، في نفس أهمية توفر نظامي نسخ احتياطي ومراقبة فعالين؛ إلا أنه يمكن أن يكون مفيدا جدا عند البحث في اتجهات استخدام التطبيق أو أثناء محاولة تحديد المشاكل التي يعاني منها التطبيق. سنعد في هذا الدليل حزمة برامج ELK، ونعني بها Logstash، Elasticsearch وKibana؛ ثم نعد مختلف الخواديم المكونة لبيئة الإنتاج حتى ترسل السجلات المناسبة إلى خادوم السجلات. سنعد أيضا مُرشِحات Filters في Logstash من أجل تجزئة السجلات وهيكلتها وهو ما يسهِّل عملية البحث في السجلات وترشيحها ثم استخدام Kibana لمعاينتها. المتطلباتيجب، إن أردت الوصول إلى لوحة المراقبة عبر نطاق خاص مثل logging.example.com، إنشاء سجل من نوع A ضمن إعدادات النطاق يحيل إلى عنوان IP العمومي الخاص بخادوم السجلات. أو يمكنك بدلا من ذلك الوصول إلى لوحة التسجيلات باستخدام عنوان الخادوم العمومي. يُنصح بإعداد خادوم السجلات لاستخدام HTTPS وتقييد الوصول إليه بوضعه في شبكة خاصة افتراضية. تثبيت حزمة ELK على خادوم السجلاتاضبط حزمة ELK على خادوم السجلات باتباع خطوات درس كيف تثبت Logstash، Elasticsearch وKibana 4 على خادوم Ubuntu 14.04. تأكد من اتباع الخيار رقم 2 في فقرة توليد شهادات SSL. توقف عند الوصول إلى فقرة ضبط معيد توجيه Logstash. إعداد معيدي توجيه Logstash على العملاءاضبط معيد توجيه Logstash (مُرسِل للسجلات) على الخواديم العميلة (مثلا db1، app2، app1 وlb1) باتباع فقرة ضبط معيد توجيه Logstash في درس ELK. سيمكنك بعد إكمال الإعداد الدخولُ إلى Kibana عبر العنوان العمومي لخادوم السجلات وعرض سجلات النظام الخاصة بخواديمك. تحديد السجلات المراد جمعهاتتيح برامج ELK الكثير من السجلات لجمعها، حسب نوعية البرامج المثبتة على الخواديم وإعدادها. سنجمع، في مثالنا، السجلات التالية: سجل الاستعلامات Queries البطيئة في MySQL (الخادوم db1).سجلات الأخطاء والوصول في Apache (على الخادومين app1 وapp2).سجلات HAProxy (خادوم توزيع الحمل lb1).اخترنا هذه السجلات بالضبط لأن بإمكانها توفير معلومات مفيدة أثناء استكشاف الأخطاء وإصلاحها أو عند محاولة تحديد توجهات المستخدمين. يمكن أن يكون لدى خادومك سجلات أخرى مهمة، حسب إعداداتك. إعداد سجلات MySQLيحفظ MySQL الاستعلامات البطيئة في سجل على المسار var/log/mysql/mysql-slow/. يتضمن السجل الاستعلامات التي أخذت وقتا طويلا للتنفيذ؛ يمكن أن يساعد تحديد هذه الاستعلامات في تحسين التطبيق والبحث عن علله وإصلاحها. تفعيل تسجيل الاستعلامات البطيئة في MySQLتسجيل الاستعلامات البطيئة في MySQL غير مفعَّل في الإعدادات الافتراضية؛ لذا سنحتاج لتفعيله. افتح ملف إعدادات MySQL لتحريره: sudo nano /etc/mysql/my.cnfابحث عن التعليمة log_slow_queries وانزع علامة التعليق # الموجودة أمامها ليصبح السطر على النحو التالي: log_slow_queries = /var/log/mysql/mysql-slow.logاحفظ الملف ثم أغلقه. تجب إعادة تشغيل MySQL لاعتماد التغييرات: sudo service mysql restartسيبدأ MySQL الآن في تسجيل الاستعلامات التي تأخذ وقتا طويلا للتنفيذ. ملف السجل يوجد على المسار المحدّد في الإعداد. إرسال ملفات سجلات MySQLيجب إعداد معيد التوجيه في Logstash لإرسال سجلات الاستعلامات البطيئة إلى خادوم السجلات. حرر ملف إعداد معيد التوجيه على خادوم قاعدة البيانات db1: sudo nano /etc/logstash-forwarder.confأضف الأسطر التالية في آخر فقرة files لإرسال الاستعلامات البطيئة إلى خادوم السجلات وتحديد نوع السجل ب mysql-slow , { "paths": [ "/var/log/mysql/mysql-slow.log" ], "fields": { "type": "mysql-slow" } } احفظ الملف ثم أغلقه. تعد التعليمات السابقة معيد توجيه Logstash لإرسال سجلات الاستعلامات البطيئة إلى خادوم السجلات وتعليمها بmysql-slow. سنستخدم نوع السجل لاحقا في الترشيح. أعد تشغيل معيد التوجيه للبدء في إرسال السجلات: sudo service logstash-forwarder restartمرماز Codec المدخلات متعددة الأسطرسنحتاج لتفعيل مرماز تعدد الأسطر في Logstash لمعالجة سجلات الاستعلامات البطيئة في MySQL التي تأتي على أسطر متعددة. افتح ملف الإعدادات الذي يعرِّف مدخل Lumberjack على خادوم logging: sudo nano /etc/logstash/conf.d/01-lumberjack-input.confأضف الأسطر التالية إلى تعريف lumberjack: codec => multiline { pattern => "^# User@Host:" negate => true what => previous }احفظ الملف ثم أغلقه. تعد التعليمات أعلاه Logstash لاستخدام معالج السجلات متعددة الأسطر عند العثور على سجلات تحتوي على النمط Pattern المُحدَّد (أي تلك التي تبدأ ب # User@Host: ). في ما يلي سنضبط مرشح Logstash لسجلات MySQL. مرشح سجلات MySQLافتح ملفا جديدا على خادوم السجلات logging لإضافة مرشحات لسجل MySQL. سنسمي الملف 11-mysql.conf لكي يُقرأ بعد إعداد مدخلات Logstash (موجودة في ملف 01-lumberjack-input.conf): sudo nano /etc/logstash/conf.d/11-mysql.confأضف تعريف المرشح التالي: filter { # يسجل المستخدم واختياريا اسم المستضيف وعنوان IP if [type] == "mysql-slow" { grok { match => [ "message", "^# User@Host: %{USER:user}(?:\[[^\]]+\])?\s+@\s+%{HOST:host}?\s+\[%{IP:ip}?\]" ] } # يسجل مدة تنفيذ الاستعلام، مدة قفل السطر في قاعدة البيانات، الأسطر المُرجعة في النتيجة والأسطر المفحوصة. grok { match => [ "message", "^# Query_time: %{NUMBER:duration:float}\s+Lock_time: %{NUMBER:lock_wait:float} Rows_sent: %{NUMBER:results:int} \s*Rows_examined: %{NUMBER:scanned:int}"] } # يسجل وقت حدوث الاستعلام grok { match => [ "message", "^SET timestamp=%{NUMBER:timestamp};" ] } # يستخرج الوقت اعتمادا على وقت الاستعلام بدلا من وقت إدراج العنصر في السجلات date { match => [ "timestamp", "UNIX" ] } # يحذف حقل الختم الزمني من السجل نظرا لتسجيل وقت الحدث (الاستعلام) mutate { remove_field => "timestamp" } } } احفظ الملف ثم أغلقه. تعد التعليمات Logstash لترشيح السجلات من نوع mysql-slow باستخدام أنماط Grok المحددة في تعليمات match. راجع التعليقا فوق كل تعليمة لأخذ نبذة عن عملها. لكي تبدأ هذه المرشحات عملها يجب أن نعيد تشغيل Logstash: sudo service logstash restartيجب التأكد في هذه المرحلة من أن Logstash يعمل بطريقة صحيحة؛ إذ أن أخطاء الإعداد قد تتسبب في إخفاق إعادة تشغيله. يجب أن تتأكد أيضا أن Kibana قادر على رؤية سجلات MySQL المرشحة. سجلات Apacheتوجد سجلات Apache عادة على المسار var/log/apache2/ باسم access.log و error.log. يتيح لك جمع هذه السجلات معرفة عناوين IP التي تتصل بخواديمك، طلبات هذه العناوين ونوعية المتصفحات ونظم التشغيل المستخدمة في الاتصال؛ بالإضافة إلى الأخطاء التي يبلغ عنها Apache. إرسال سجلات Apacheنضبط معيد توجيه Logstash لإرسال سجلات الوصول والأخطاء في Apache إلى خادوم logging. نفذ الأمر التالي على كل واحد من خادومي التطبيق، app1 وapp2 لفتح ملف إعاد الخاص بمعيد توجيه Logstash: sudo nano /etc/logstash-forwarder.confأضف ما يلي ضمن فقؤة files تحت التعليمات الموجودة: , { "paths": [ "/var/log/apache2/access.log" ], "fields": { "type": "apache-access" } }, { "paths": [ "/var/log/apache2/error.log" ], "fields": { "type": "apache-error" } } احفظ الملف ثم أغلقه. تعد هذه التعليمات معيد توجيه Logstash لإرسال سجلات الوصول والأخطاء في Apache إلى خادوم السجلات، ثم تعليم كل سجل بنوعه (أي apache-access بالنسبة للوصول وapache-error بالنسبة للأخطاء). أعد تشغيل معيد التوجيه للبدء في إرسال السجلات: sudo service logstash-forwarder restartإذا تركنا الإعداد الحالي فستُظهر كل سجلات Apache عنوان IP الخاص لخادوم HAProxy بوصفه عنوان المصدر. يعود السبب في ذلك إلى أن الخادوم الوسيط lb1 هو الوسيلة الوحيدة للوصول إلى خواديم التطبيق من الإنترنت. يمكن تغيير هذا الأمر بإعداد الصيغة الافتراضية لسجل Apache بحيث يستخدم الرأسيات X-Forwarded-For التي يرسلها HAProxy. افتح ملف إعداد Apache على كل واحد من خادومي التطبيقات: sudo nano /etc/apache2/apache2.confابحث عن سطر يظهر على النحو التالي: [Label apache2.conf — Original "combined" LogFormat] LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined أبدل: h% ب%{X-Forwarded-For}i لكي تصبح هيئة السطر كالتالي: [Label apache2.conf — Updated "combined" LogFormat] LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined احفظ الملف ثم أغلقه. بهذا نكون أعددنا سجلات Apache لتضمين عنوان IP المصدر الفعلي بدلا من عنوان IP الخاص لخادوم توزيع الحمل. أعد تشغيل Apache لاعتماد التغييرات: sudo service apache2 restartنحن الآن جاهزون لإضافة مرشحات لسجلات Apache في Logstash. مرشحات سجلات MySQLننشئ ملف إعداد جديدا على خادوم السجلات logging من أجل إضافة مرشحات لسجل Apache إلى Logstash. سنسميه 12-apache.conf لكي يقرأه Logstash بعد ملف إعداد المُدخلات (أي ملف 01-lumberjack-input.conf): sudo nano /etc/logstash/conf.d/12-apache.confأضف تعريفات المرشحات التالية: filter { if [type] == "apache-access" { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } } } filter { if [type] == "apache-error" { grok { match => { "message" => "\[(?<timestamp>%{DAY:day} %{MONTH:month} %{MONTHDAY} %{TIME} %{YEAR})\] \[%{DATA:severity}\] \[pid %{NUMBER:pid}\] \[client %{IPORHOST:clientip}:%{POSINT:clientport}] %{GREEDYDATA:error_message}" } } } } احفظ الملف ثم أغلقه. تعد هذه التعليمات Logstash لاستخدام مرشحات Grok لتحليل سجلات الوصول والأخطاء في Apache. يعرف كل مرشح صيغة السجلات التي يتعامل معها ضمن تعليمة match الموجودة في المرشح الموافق لنوع السجل في الاسم. يُستخدم مرشح Grok يوفره Logstash لتحليل سجلات الوصول إلى Apache اعتمادا على الصيغة الافتراضية لهذه السجلات؛ بينما كتبنا مرشح Grok خاص لتحليل الصيغة الافتراضية لسجل الأخطاء في Apache. نعيد تشغيل Logstash لكي تبدأ المرشحات الجديدة عملها: sudo service logstash restartيجب التأكد في هذه المرحلة من أن Logstash يعمل بطريقة صحيحة؛ إذ أن أخطاء الإعداد قد تتسبب في إخفاق إعادة تشغيله. يجب أن تتأكد أيضا أن Kibana قادر على رؤية سجلات Apache المرشحة. سجلات HAProxyيسمح جمع سجلات موزع الحمل HAProxy (توجد عادة في الملف var/log/haproxy.log/) بمعرفة عناوين IP التي تتصل بخادوم توزيع الحمل، ماذا تطلب، خادوم التطبيق الذي يجيب على الطلب، ومعلومات مفصَّلة أخرى عن الاتصال. إرسال ملفات السجلات الخاصة بHAProxyنضبط معيد توجيه Logstash لإرسال سجلات HAProxy إلى خادوم السجلات بنفس طريقة الإعداد التي اتبعناها مع الخواديم السابقة. افتح الملف التالي على خادوم توزيع الحمل lb1: sudo nano /etc/logstash-forwarder.confأضف الأسطر التالية إلى فقرة files تحت التعليمات الموجودة سلف. ترسل التعليمات الجديدة سجلات HAProxy إلى خادوم Logstash وتحدد نوعها بـ haproxy-log. , { "paths": [ "/var/log/haproxy.log" ], "fields": { "type": "haproxy-log" } } احفظ الملف ثم أغلقه. تعد التعليمات أعلاه Logstash لإرسال سجلات HAProxy مع تحديد نوعها بhaproxy-log. يستخدَم النوع في ما بعد لترشيح السجلات. أعد تشغيل معيد توجيه في Logstash للبدء في إرسال السجلات: sudo service logstash-forwarder restartمرشح سجلات HAProxyافتح ملفا جديدا على خادوم logging لإضافة مرشح سجلات HAProxy إلى Logstash. سنسمي الملف الجديد 13-haproxy.conf: sudo nano /etc/logstash/conf.d/13-haproxy.confأضف تعريف المرشح التالي: filter { if [type] == "haproxy-log" { grok { match => { "message" => "%{SYSLOGTIMESTAMP:timestamp} %{HOSTNAME:hostname} %{SYSLOGPROG}: %{IPORHOST:clientip}:%{POSINT:clientport} \[%{MONTHDAY}[./-]%{MONTH}[./-]%{YEAR}:%{TIME}\] %{NOTSPACE:frontend_name} %{NOTSPACE:backend_name}/%{NOTSPACE:server_name} %{INT:time_request}/%{INT:time_queue}/%{INT:time_backend_connect}/%{INT:time_backend_response}/%{NOTSPACE:time_duration} %{INT:http_status_code} %{NOTSPACE:bytes_read} %{DATA:captured_request_cookie} %{DATA:captured_response_cookie} %{NOTSPACE:termination_state} %{INT:actconn}/%{INT:feconn}/%{INT:beconn}/%{INT:srvconn}/%{NOTSPACE:retries} %{INT:srv_queue}/%{INT:backend_queue} "(%{WORD:http_verb} %{URIPATHPARAM:http_request} HTTP/%{NUMBER:http_version})|<BADREQ>|(%{WORD:http_verb} (%{URIPROTO:http_proto}://))"'} } } } احفظ الملف ثم أغلقه. تعد التعليمة Logstash لترشيح السجلات من نوع haproxy-log باستخدام نمط Grok المعيَّن، والذي يحلل السجلات لمطابقتها مع الصيغة الافتراضية لسجلات HAProxy. أعد تشغيل Logstash لاعتماد المرشح: sudo service logstash restartيجب التأكد بعد تنفيذ الأمر أن Logstash يعمل بطريقة صحيحة؛ إذ أن أخطاء الإعداد قد تتسبب في إخفاق إعادة تشغيله. إعداد المعاينة باستخدام Kibanaيمكن البدء باستخدام Kibana لمعاينة السجلات التي جمعناها من مختلف الخواديم. يسعادك المقال التالي في البدء باستخدام Kibana: كيف تستخدم لوحات القيادة والمعاينة في Kibana بعد التأقلم مع Kibana جرب درس كيف تظهر مواقع المستخدمين على خريطة باستخدام GeoIP وELK لمعاينة أكثر تقدما. خاتمةإن اتبّعت الخطوات المشروحة في هذا الدليل فستحصل على بيئة إنتاج مثل تلك التي وصفناها في الجزء الأول نظرة عامة على إنشاء تطبيقات موجهة لبيئة الإنتاج من الدليل. ترجمة - وبتصرف - لمقال Building for Production: Web Applications — Centralized Logging لصاحبه Mitchell Anicas.
  4. تَستخدم المُرشّحات في Angular نمط خطّ الأنابيب (pipeline) بشكلٍ مشابه للـUnix shell، فقد استعارت رمز الخطّ العمودي المشابه لرمز الأنبوب من Unix لتستخدمه لتمرير عبارات التّهيئة أو خواص المجال للمُرشّح وأيضًا لربط المُرشّحات معًا. سنقوم بتحميل إطار عمل Bootstrap الخاصّ بـCSS لأننا سنقوم بإنشاء بعض الجداول في أمثلة هذا الفصل ممّا سيجعلها أكثر ترتيبًا، وسنجلبه من شبكة توصيل المحتوى (CDN) كما تُبيّن الشّيفرة التّالية. <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js"></script>ستسخدم الأمثلة أيضًا المتحكمات و الخدمات لتحضير البيانات للعرض، لذا سنقوم بتعريف وحدة جذرٍ لإداراتهم. angular.module('app', []);سنقوم بإسناد اسم وحدة الجذر لتطبيقنا إلى التّوجيه ng-app. <body ng-app="app"> <!-- الأمثلة توضع هنا --> </body>مفهوم المُرشّحات سهلُ التّعلّم، لذا سيكون هذا الفصل مرورًا سريعًا على المُرشّحات المبنيّة داخل Angular، ثُمّ سنستعرض كيف يمكننا إنشاء المُرشّحات الخاصّة بنا. lowercase و uppercaseلنبدأ جولتنا مع المُرشّحات المبنيّة في Angular ببعض التّحويلات على السّلاسل النّصية، والمُرشّح lowercase بدايةٌ ممتازة. نبدأ بكتابة أيّ عبارة (في مثالنا استخدمنا عبارة "AngularJS")، ثم نضع رمز الأنبوب (|)، وبعده نكتب اسم المُرشّح (lowercase). <p>{{"AngularJS" | lowercase}}</p>الناتج: angularjsيُمكننا تطبيق المرشّح uppercase على النّتيجة عن طريق إضافة رمز أنبوبٍ آخر، ثمّ اسم المرشّح، وهذا ما نُسمّيه بسلسلة المُرشّحات. <p>{{"AngularJS" | lowercase | uppercase }}</p>الناتج: ANGULARJSبالطّبع ليس هناك فائدةٌ من وضع lowercase قبل uppercase، وسنرى في نهاية هذا الفصل مثالًا أفضل على سَلسَلة المُرشّحات، ولكن على الأقل رأينا كيف نقوم بذلك الآن. numberالمُرشّح التّالي سهلٌ أيضًا، المُرشّح number يُقدّم المساعدة الأساسيّة لتنسيق الأعداد وتقريبها. <p>{{1000.12345 | number}}</p>الناتج: 1,000.123بالنّسبة لإعداداتي المحلّيّة، en-us، المُخرجات في المثال هي 1,000.123، يقوم المُرشّح بتقريب العدد المُمرّر إليه إلى 3 خاناتٍ بعد الفاصلة، ومن الواضح أنّ هذا لن يناسب جميع الاستخدامات، ولحسن الحظ، يمكننا تمرير وسطاء إلى المرشّحات التي تقبل القيام بذلك، والمُرشّح number يقبل ذلك. الوسيط الأول الذي نقوم بتمريره هو القيمة التي نريد تطبيق المُرشّح عليها، أما الوسيط الإضافي الثّاني فيجب أن يتبع اسم المُرشّح ويكون مفصولًا عنه بنقطتين (:). الوسيط الإضافيّ الثّاني للمُرشّح number هو fractionSize، وهو يسمح لنا بالتّحكّم بعدد المنازل التي يتم عرضها بعد الفاصلة، وبهذا يمكننا رؤية القيمة كاملةً. <p>{{1000.12345 | number:5}}</p>الناتج: 1,000.12345ماذا يحدث لو قمنا بتمرير قيمةٍ سالبةٍ إلى الوسيط fractionSize؟ استبدل 5 بـ 3- ثمّ جرّب 4-، هل يُمكنك تخمين السّبب؟ لا مشكلة، حتى أنا لا يمكنني ذلك. currencyالمُرشّح التّالي مفيدٌ بعض الشّيء في التّطبيقات العمليّة: يُقدّم المُرشّح currency الدّعم الأساسيّ لتنسيق العملة وتقريب قيمة العدد. <p>{{1999.995 | currency}}</p>الناتج: $2,000.00وهو يقبل وسيطين إضافيين، أوّلهما هو رمز العملة، استبدل currency بـ'€':currency في المثال السّابق لتجريبه. الوسيط الثّاني هو fractionSize. انتبه عند استخدامك للمُرشّح currency عند تقريب المبَالِغ الماليّة، فليس هناك طريقةٌ واحدةٌ فقط هي الصّحيحة عندما ننظر للأمر على أنّه مسألةٌ ماليٌّةٌ وليست تقنيًّة، فهذا المُرشّح يستخدم تقريب النصف للأعلى وقد لا يكون هذا جيّدًا دومًا، كما رأينا في المثال السّابق. لا يوجد حاليًّا طريقةٌ موثّقةٌ لتجاوز طريقة المُرشّح في التّقريب، ما رأيك بأن تحاول التّعديل على المثال السّابق لتجعل المُرشّح يعرض القيمة الصّحيحة. dateسيبيّن المُرشّح date لك إلى أيّ مدىً تذهب بك إعدادات المُرشّحات. لا تسمح Angular بتهيئة كائنٍ من نوع Date داخل عبارة، لذا سنستخدم متحكّمًا لتحضير النّموذج الخاصّ بالمثال. angular.module('app') .controller('DateController', function($scope) { $scope.now = Date.now(); });يبدأ المثال التّالي بعنصرٍ في المجال اسمه now، بدلًا من كتابة عبارة. <p ng-controller="DateController"> {{now | date}} </p>الناتج: Oct 28, 2015إن قمت بإزالة date | من المثال السّابق سترى القيمة الأصليّة للعنصر now، وهي عدد الميللي ثانية منذ شهر كانون الثّاني عام 1970 حسب التوقيت العالميّ UTC. والآن قم بتجربة بعض التّنسيقات المُعرّفة سابقًا، والتي يدعمها هذا المُرشّح، قم بتجربة 'date:'medium | ثمّ 'date:'shortTime | وبعدها 'date:'yyyy-MM-dd HH:mm:ss Z |، وجرّب بعض التّعديلات من عندك بعد ذلك. يُسمح بكتابة السّلاسل المحرفية داخل نمط التّنسيق، مثلًا "date:"MMMM 'of the year' yyyy |، وبدلًا من استخدام محارف الهروب مثل % لوضع رموز التّنسيق، سيكون عليك وضع السّلاسل المحرفية بين علامتَي تنصّيّصٍ مفردة (') وأن تكون عبارة التّنسيق الكاملة بين علامتَي تنصّيّصٍ مزدوجة ("). كما أنّ الفراغات في عبارة التّنسيق تدخل في تنسيق العبارة. orderByيُمكن للمُرشّحات القيام بما هو أكثر من تنسيق المخرجات، حيث يُمكن استخدمها لتحويل المجموعات، كما سنرى في المثال التّالي. لنفترض أنّ خدمةً في النهاية الخلفية (backend) أَرجعت سجلًّا مرتًبًا بطريقةٍ غير مرغوبةٍ لأسباب تتعلّق بالعرض. (لتبسيط المثال، ستكون البيانات مكتوبةً يدويًّا داخل الخدمة items التي تراها أدناه، وذلك بدلًا من التّعامل مع نهايةٍ خلفيّة بعيدة حقيقيّة.) angular.module('app') .value('items', [ {name: 'Item 3', position: 3, color: 'red', price: 2.75}, {name: 'Item 1', position: 1, color: 'red', price: 0.92}, {name: 'Item 4', position: 4, color: 'blue', price: 3.09}, {name: 'Item 2', position: 2, color: 'red', price: 1.95} ]);سنقوم بعد ذلك بحقن المصفوفة items في داخل متحكّم. angular.module('app') .controller('ItemsController', function($scope, items) { $scope.items = items; });بناءً على ترتيب العناصر الحالي في المصفوفة، كيف يمكننا ترتيب العناصر حسب قيمة العنصر position؟ إن كنتَ قد قفزتَ من مقعدك الآن وصرخت قائلًا "Underscore" (أو "lodash")، فتستحقّ منّي وسام الوفاء لـJavaScript، ولكنّها ليست الإجابة التي نبحث عنها، فـAngular تملك مُرشّحًا للقيام بذلك، إنّه المُرشّح orderBy. <ol ng-controller="ItemsController"> <li ng-repeat="item in items | orderBy:'position'"> {{item.name}} </li> </ol>الناتج: 1. Item 1 2. Item 2 3. Item 3 4. Item 4هذا رائع، ولكن ماذا لو أردنا أن يكون التّرتيب بالجهة المعاكسة؟ في هذا المثال البسيط يمكننا القيام بذلك بطريقتين، الأولى هي إضافة الرمز - قبل اسم العنصر، أي أن نكتب 'orderBy:'-position بدلًا من 'orderBy:'position. (يمكنك أيضًا إضافة الرمز + لاختيار التّرتيب التّصاعدي، إلا أنّه لا يؤثّر على مثالنا السّابق.) أمّا الطّريقة الثّانية فهي إعطاء قيمةٍ للوسيط البولياني reverse بعد اسم العنصر المطلوب التّرتيبُ حسب قيمته. في مثالنا، قم بكتابة orderBy:'position':true بدلًا من 'orderBy:'position. فائدةٌ إضافيّة: عدّل سجلّ البيانات في المتحكّم بحيث تجعل عنصرين في المصفوفة لهما القيمة نفسها بالنّسبة للعنصر position، ألا يزال بإمكانك استخدام المُرشّحorderBy لترتيب العناصر بشكلٍ صحيح؟ ماهي الخاصّيّة التي استخدمتها؟ انتبه للتحديثاتبفضل طريقة Angular في الربط ثنائيّ الاتّجاه، سيكون من السّهل جدًّا أن تجعل النّماذج في قائمة أو جدول العرض قابلةً للتّعديل، كلّ ما تحتاجه هو إضافة خانة إدخالٍ داخل الحلقة مع إسناد اسم عنصر المجموعة إلى التّوجيه ng-model. ولكن انتبه، فبما أنّ Angular جاهزةٌ دومًا وتنتظر إعادة توليد العرض عند أيّ تغيير في الحالة، فقد يتمّ إعادة ترتيب قائمتك قبل أن تنتهي من تعديل العنصر حتّى. <table class="table table-condensed" ng-controller="ItemsController"> <tr ng-repeat="item in items | orderBy:'name'"> <td ng-bind="item.name"></td> <td><input type="text" ng-model="item.name"></td> </tr> </table> جرّب تعديل اسم أحد العناصر في المثال السّابق بحذف المحتوى أوّلًا ثمّ كتابة الأحرف، وستلاحظ مشكلةً كبيرةً في الاستخدام. فـAngular تقوم بإعادة توليد الجدول كاملًا، ونقل السطر إلى مكانٍ آخر قبل أن تنتهي من كتابته. أفضل الحلول لهذه المشكلة قد يكون استخدام عرضٍ(view) آخر منفصلٍ للتّعديل، كما يمكنك نقل المُرشّح orderBy من العرض إلى المتحكّم حيث يتمّ استدعاؤه مرّةً واحدة، وهذا ما سنتكّلم عنه في الفقرة القادمة، استخدام المرشحات في JavaScript. limitToالمُرشّح limitTo مفيدٌ عندما ترغب بعرض مجموعةٍ جزئيّةٍ فقط من مجموعةٍ مرتّبة. مثلًا، يمكننا استخدامها بالتّعاون مع المُرشّح orderBy لنعرض فقط أغلى عنصرين في المجموعة. <ol ng-controller="ItemsController"> <li ng-repeat="item in items | orderBy:'-price' | limitTo:2"> {{item.price | currency}} </li> </ol>الناتج: 1. $3.09 2. $2.75لا تُقدّم Angular طريقةً لتمرير وسيط offset إلى المُرشّح limitTo حاليًّا. ولتقديم حلٍّ كاملٍ للتصحيف (pagination) سيتضمّن ذلك استخدام التّابع slice داخل المتحكّم. filterاسم هذا المُرشّح ظريفٌ نوعًا ما، فهو مرشّحٌ اسمه filter، ربّما لم يكن من المناسب تسمية المُرشّحات بهذا الاسم العام (ربّما يكون الاسم مزخرِفات أو مساعِدات أفضل)، إلّا أنّ هذا المرشّح يقوم فعلًا بالتّرشيح. فهو يقوم بإعادة مصفوفةٍ تحوي فقط على العناصر التي تطابق الشرط المُسند. لنرى ما هي العناصر التي ستطابق وضعنا لشرطٍ يقول بأنّ القيمة العدديّة تساوي 3. <table class="table table-condensed" ng-controller="ItemsController"> <thead> <tr><th>name</th><th>color</th><th>price</th></tr> <thead> <tbody> <tr ng-repeat="item in items | filter:3"> <td ng-bind="item.name"></td> <td ng-bind="item.color"></td> <td ng-bind="item.price | currency"></td> </tr> <tbody> </table>لقد حصلنا على تطابقات في كلا العنصرين name وprice. ماذا سيحدث لو استبدلنا الشرط 3 بالسّلسلة النّصية '3' أو بسلسلة نصّيّة خالية؟ أو لو أضفنا فراغًا في البداية ('3 ')؟ لتجنُّب مطابقة أيّ عنصرٍ، يمكنك تمرير كائنٍ باعتباره شرط التّطابق. <table class="table table-condensed" ng-controller="ItemsController"> <thead> <tr><th>name</th><th>color</th><th>price</th></tr> <thead> <tbody> <tr ng-repeat="item in items | filter:{price: 2, color: 'red'}"> <td ng-bind="item.name"></td> <td ng-bind="item.color"></td> <td ng-bind="item.price | currency"></td> </tr> <tbody> </table>في المثال السّابق، لم يتمّ مطابقة 2 مع item 2 لأننا حدّدنا اسم عنصر التّطابق بأنّه price. أكثر ما يجعل المُرشّح filter رائعًا، هو السهولة الفائقة في دمجه مع الربط ثنائيّ الاتّجاه في Angular، لإنتاج صندوق ترشيحٍ قويّ. Filter: <input type="text" ng-model="q"> <table class="table table-condensed" ng-controller="ItemsController"> <thead> <tr><th>name</th><th>color</th><th>price</th></tr> <thead> <tbody> <tr ng-repeat="item in items | filter:q"> <td ng-bind="item.name"></td> <td ng-bind="item.color"></td> <td ng-bind="item.price | currency"></td> </tr> <tbody> </table>إن كان هناك مثالٌ واحدٌ يبيّن بأفضل طريقةٍ مرونة وقوّة امتدادات HTML التي توفّرها Angular، فقد يكون هذا هو. استخدام المرشحات في JavaScriptتحتاج أحيانًا إلى استخدام مُرشّح ما عندما يكون لديك القوّة الكاملة لـJavaScript، بدلًا من أن تكون محدودًا بما تسمح لك العبارات بالقيام به. مثلًا، أمرٌ بسيطٌ كمعرفة عدد العناصر التي أنتجها المُرشّح، لا يبدو ممكنًا. ربما يمكنك أن تقول بأنّه عندما تصبح العبارة كبيرةً وتحتاج إلى منطقٍ برمجيٍّ فمن الأفضل نقل شيفرتها إلى داخل متحكّم. <p ng-controller="ItemsController"> <!-- Invalid code! --> {{items | filter:{color:'red'}.length}} red items </p>الناتج: [{"name":"Item 3","position":3,"color":"red","price":2.75},{"name":"Item 1","position":1,"color":"red","price":0.92},{"name":"Item 4","position":4,"color":"blue","price":3.09},{"name":"Item 2","position":2,"color":"red","price":1.95}] red itemsيُمكنك حقن المُرشّحات أينما أردت، كما أنّه ليس من الغريب استخدام المُرشّح filter للتعامل مع مصفوفةٍ داخل متحكّم. يكون اسم التّابع الذي يقوم بالترشيح من الشكل filtername>Filter>. مثلًا لاستخدام المُرشّح date نقوم بحقن dateFilter، لاستخدام المُرشّح currency نقوم بحقن currencyFilter، ولاستخدام المُرشّح filter نقوم بحقن filterFilter. (أعرف ذلك، أعرف ذلك) angular.module('app') .controller('FilteredItemsController', function($scope, items, filterFilter) { $scope.redItemsCount = filterFilter(items, {color: 'red'}).length; });<p ng-controller="FilteredItemsController"> {{redItemsCount}} red items </p>الناتج: 3 red itemsما عليك إبقاؤه في ذهنك بشكلٍ أساسيّ هو أنّ استخدام المُرشّح داخل المتحكّم بدلًا من أن يكون في العرض، سيؤدي إلى عدم استدعاء المُرشّح عند حدوث تغييرات في واجهة المستخدم إن كانت تغييراتٍ لا تتضمّن إعادة استدعاء المتحكّم. ولحلّ هذه المشكلة يمكنك ربط استخدام المُرشّح يدويًّا بعنصرٍ في المجال باستخدام التابع scope.$watch. مرشح مخصصالمُرشّح المخصّص هو أفضل مكانٍ لتضع فيه الشيفرات التي تقوم بتحويل بيانات النّموذج للعرض، وذلك لأنّ المُرشّح نموذجيًّا مكوِّنٌ ثابت الحالة (stateless) ويُمكن استخدامه في أيّ مكانٍ داخل القوالب دون خوفٍ من أيّ تأثيراتٍ جانبيّة، كما أنّ إنشاء مُرشّح مخصّص ليس صعبًا، فبشكلٍ مشابهٍ لبقيّة المكوّنات في Angular، نقوم بتسجيل وصفةٍ للمُرشّح داخل الوحدة، باستخدام التّابع filter. angular.module('app') .filter('smiley', function() { return function(text) { return '\u263A ' + text + ' \u263A'; }; });في المثال السّابق، المُرشّح الفعليّ هو التابع الدّاخليّ الذي يقوم بوصل السّلسلة النّصية الممرّرة إليه عن طريق الوسيط text مع رمز الوجه الضاحك. يتم استدعاءُ هذا التابع في كلّ مرّة يتمّ فيها استدعاء المُرشّح، أمّا التابع الخارجيّ الذي يحيط بالمُرشّح فهو وصفة (recipe) إنشائية، وقد ناقشنا هذه الفكرة بعمقٍ في الفصل السّابق، الخدمات. يتمّ تشغيل الوصفة مرّةً واحدةً، أو لا يتمّ تشغيلها أبدًا إن لم يكن لها استخدامٌ في العرض. المُرشّحات المخصّصة تكون متوفّرة تلقائيًّا في أيّ مكانٍ في العرض، ويتمّ استخدامها تمامًا مثل المُرشّحات الأصليّة في المكتبة، حيث نقوم ببساطةٍ بإدخال العبارة فيأنبوب الترشيح داخل العرض، وذلك باستخدام رمز الأنبوب (|)، ويتم تمرير قيم الوسطاء الإضافيّة باستخدام رمز النّقطتين (:). <strong ng-bind="'hello' | smiley"></strong>الناتج: ☺ hello ☺إليك هذا التّحدّي: هل يمكنك إعادة تشكيل المُرشّح بحيث يصبح بإمكاننا تمرير رمز الوجه الضّاحك كوسيط؟ حقن التبعيةبالرغم من كون المُرشّحات ثابتة الحالة وبسيطةً نوعًا ما، إلّا أنّها يمكن أن تملك تبعيّاتٍ تحتاج إلى أن تُحقن. يسمح تابع الوصفة الإنشائيّة الخارجيّ بالتّصريح عن التّبعيّات تمامًا كما نقوم بذلك في الوحدات. فلنلقِ نظرةً على الكيفيّة التي نقوم بها بحقن التّبعيّات في داخل مُرشّح مخصّص للمحلّيّات (localization). سنقوم بتسمية المُرشّح بالاسم localize، ولكن قبل ذلك نحتاج إلى شيءٍ ما لنقوم بالحقن. يمكننا إنشاء جدول لمحتوى المتغيّر locales، حيث يتمّ تعريفها كخدمةٍ قابلةٍ للحقن باستخدام التّابع value. angular.module('app') .value('locales', { 'de': {greeting: 'guten Tag'}, 'en-us': {greeting: 'howdy'}, 'fr': {greeting: 'bonjour'} });يمكننا حقن هذه البيانات في داخل مُرشّحنا البسيط المخصّص بالتّصريح عن وسيطٍ اسمه locales، ولنتمكّن من الحصول على الموضع الحاليّ للمستخدم، يُمكننا استخدام الخدمة locale$ المبنيّة داخل Angular . angular.module('app') .filter('localize', function(locales, $locale) { return function(key) { var locale = locales[$locale.id] || locales['en-us']; return locale[key]; }; });سيعمل المثال السّابق معك فقط إن كانت إعدادات جهازك المحلّيّة من ضمن الأماكن المحدّدة في المثال، إن لم يكن موضعك موجودًا فقم بإضافته بنفسك مع عبارةٍ ترحيبيّة بلغتك. <p> The app says <strong ng-bind="'greeting' | localize"></strong>. </p>الناتج: The app says howdy.يُمكنك أيضًا أن تقوم بحقن المُرشّحات في داخل مُرشّح آخر. يمكنك نقل الوسطاء الكثيرة وسلاسل المُرشّحات الطويلة إلى مُرشّح مخصّص، وهذه طريقةٌ رائعةٌ لإزالة بعض الضجّة من شيفرة العرض. خاتمةالمُرشّحات المبنيّة في Angular جزءٌ هامٌّ من قدراتها الرائعة، كما أنّ استخدامها سهلٌ وبديهيّ بشكلٍ عامٍّ، كما أنّها مرنة بفضل الوسطاء الإضافيّة وسَلسلة المُرشّحات، وأيضًا فإنّ إنشاء مرشّحٍ مخصّص سيكون سهلًا فورَ إتقانك لنمط الوصفة الإنشائيّة (creation recipe) التي تسمح لك بحقن التّبعيّات. والآن بعد أن اعتدنا استخدام هذه الأنماط، فنحن الآن جاهزون للتّحدّي في الفصل القادم، حيث سنقوم بإعداد التّوجيهات الخاصّة بنا. ترجمة وبتصرّف للفصل التاسع من كتاب: Angular Basics لصاحبه: Chris Smith.
×
×
  • أضف...