الفرق بين المراجعتين ل"Rails/action view overview"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
سطر 3: سطر 3:
 
[[تصنيف:Rails View]]
 
[[تصنيف:Rails View]]
 
بعد قراءة هذا الدليل، ستعرف:
 
بعد قراءة هذا الدليل، ستعرف:
* ما هو إجراء العرض (Action View) وكيفية استخدامه مع ريلز.
+
* ما هو Action View وكيفية استخدامه مع ريلز.
 
* أفضل طريقة لاستخدام القوالب والجزئيات (partials) والتخطيطات.
 
* أفضل طريقة لاستخدام القوالب والجزئيات (partials) والتخطيطات.
* ما الذي يقدمه المساعدون عن طريق إجراء العرض.
+
* ما الذي يقدمه المساعدون عن طريق Action View.
 
* كيفية استخدام العروض المحلية.
 
* كيفية استخدام العروض المحلية.
  
== ما هو إجراء العرض؟ ==
+
== ما هو Action View؟ ==
في ريلز، تُعَالَج طلبات الويب من خلال [[Rails/action controller overview|وحدة التحكم]] وإجراء العرض. عادةً ما يقع على عاتق وحدة التحكم التواصل مع قاعدة البيانات وتنفيذ الإجراءات CRUD عند الضرورة؛ بعد ذلك، يكون إجراء العرض مسؤولًا عن تفسير (compiling) الاستجابة.
+
في ريلز، تُعَالَج طلبات الويب من خلال [[Rails/action controller overview|Action Controller]] و Action View. عادةً ما يقع على عاتق وحدة التحكم التواصل مع قاعدة البيانات وتنفيذ الإجراءات CRUD عند الضرورة؛ بعد ذلك، يكون Action View مسؤولًا عن تفسير (compiling) الاستجابة.
  
تُكتَب قوالب إجراء العرض باستخدام [[Ruby|روبي]] المضمّنة بالوسوم التي تمزج مع [[HTML]]. لتجنب ازدحام القوالب بشيفرة نمطية، يوفر عدد من أصناف المساعد سلوكًا شائعًا للنماذج والتواريخ والسلاسل النصية. من السهل أيضًا إضافة مساعدين جدد إلى تطبيقك أثناء تطويره.
+
تُكتَب قوالب Action View باستخدام [[Ruby|روبي]] المضمّنة بالوسوم التي تمزج مع [[HTML]]. لتجنب ازدحام القوالب بشيفرة نمطية، يوفر عدد من أصناف المساعد سلوكًا شائعًا للنماذج والتواريخ والسلاسل النصية. من السهل أيضًا إضافة مساعدين جدد إلى تطبيقك أثناء تطويره.
  
'''ملاحظة''': ترتبط بعض ميزات الإجراء العرض [[Rails/active record basics|بالسجل الفعال]]، ولكن هذا لا يعني أن إجراء العرض يعتمد على [[Rails/active record basics|السجل الفعال]]. إجراء العرض هو حزمة مستقلة يمكن استخدامها مع أي نوع من مكتبات [[Ruby|روبي]].
+
'''ملاحظة''': ترتبط بعض ميزات Action View بـ [[Rails/active record basics|Active Record]]، ولكن هذا لا يعني أن Action View يعتمد على [[Rails/active record basics|Active Record]]. إنَّ Action View هو حزمة مستقلة يمكن استخدامها مع أي نوع من مكتبات [[Ruby|روبي]].
  
== استخدام إجراء العرض مع ريلز ==
+
== استخدام Action View مع ريلز ==
هناك مجلد مرتبط في المجلد app/views لكل وحدة تحكم الذي يحتفظ بملفات القالب التي تشكل العروض المرتبطة بوحدة التحكم هذه. تُستخدَم هذه الملفات لعرض الشكل التي تنتج من كل إجراء وحدة تحكم.
+
هناك مجلد مرتبط في المجلد app/views لكل وحدة تحكم الذي يحتفظ بملفات القالب التي تشكل العروض المرتبطة بوحدة التحكم هذه. تُستخدَم هذه الملفات لعرض الشكل التي تنتج من كل [[Rails/action controller overview|Action Controller]].
  
دعونا نلقي نظرة على ما يفعله ريلز افتراضيَّا عند إنشاء مصدر جديد باستخدام المولد Scaffold:<syntaxhighlight lang="shell">
+
دعنا نلقي نظرة على ما يفعله ريلز افتراضيَّا عند إنشاء مصدر جديد باستخدام المولد Scaffold:<syntaxhighlight lang="shell">
 
$ bin/rails generate scaffold article
 
$ bin/rails generate scaffold article
 
       [...]
 
       [...]
سطر 31: سطر 31:
 
       create      app/views/articles/_form.html.erb
 
       create      app/views/articles/_form.html.erb
 
       [...]
 
       [...]
</syntaxhighlight>يوجد اصطلاح تسمية للعروض في ريلز. عادةً ما تشارك العروض اسمَها مع إجراء وحدة التحكم المرتبط، كما ترى أعلاه. على سبيل المثال، سيستخدم فهرس حدث وحدة التحكم article_controller.rb ملف العرض index.html.erb في المجلد app/views/articles. الملف HTML الكامل المعاد إلى العميل يتكون من مزيج من الملف ERB هذا، وقالب تخطيط يغلفه، وكل الجزئيات (partials) التي يشير إليها العرض. ضمن هذا الدليل، ستجد توثيقًا أكثر تفصيلًا حول كل من هذه المكونات الثلاثة.
+
</syntaxhighlight>يوجد اصطلاح تسمية للعروض في ريلز. عادةً ما تشارك العروض اسمَها مع Action Controller المرتبط، كما ترى أعلاه. على سبيل المثال، سيستخدم فهرس حدث وحدة التحكم article_controller.rb ملف العرض index.html.erb في المجلد app/views/articles. الملف HTML الكامل المعاد إلى العميل يتكون من مزيج من الملف ERB هذا، وقالب تخطيط يغلفه، وكل الجزئيات (partials) التي يشير إليها العرض. ضمن هذا الدليل، ستجد توثيقًا أكثر تفصيلًا حول كل من هذه المكونات الثلاثة.
  
 
== القوالب والجزئيات والتخطيطات ==
 
== القوالب والجزئيات والتخطيطات ==
سطر 37: سطر 37:
  
 
=== القوالب ===
 
=== القوالب ===
يمكن كتابة قوالب إجراء العرض بعدة طرق. إذا كان ملف القالب بامتداد <code>erb.</code>، فإنه يستخدم خليطًا من ERB ([[Ruby|روبي]] المضمَّنة [Embedded Ruby]) و [[HTML]]. إذا كان ملف القالب بامتداد <code>builder.</code>، فستُستخدَم المكتبة <code>Builder::XmlMarkup</code>.
+
يمكن كتابة قوالب Action View بعدة طرق. إذا كان ملف القالب بامتداد <code>erb.</code>، فإنه يستخدم خليطًا من ERB ([[Ruby|روبي]] المضمَّنة [Embedded Ruby]) و [[HTML]]. إذا كان ملف القالب بامتداد <code>builder.</code>، فستُستخدَم المكتبة <code>Builder::XmlMarkup</code>.
  
 
يدعم ريلز أنظمة القوالب المتعددة ويستخدم امتدادًا للملف للتمييز بينها. على سبيل المثال، يملك الملف HTML المستخدِم لنظام القالب ERB الامتداد <code>html.erb.</code> كامتداد للملف.
 
يدعم ريلز أنظمة القوالب المتعددة ويستخدم امتدادًا للملف للتمييز بينها. على سبيل المثال، يملك الملف HTML المستخدِم لنظام القالب ERB الامتداد <code>html.erb.</code> كامتداد للملف.
سطر 189: سطر 189:
  
 
=== التخطيطات ===
 
=== التخطيطات ===
يمكن استخدام التخطيطات (Layouts) لتصيير قالب عرض شائع حول نتائج إجراءات وحدة التحكم في ريلز. عادة، سيكون لتطبيق ريلز بعض التخطيطات التي ستُصيَّر هذه الصفحات ضمنها. على سبيل المثال، قد يحتوي أحد المواقع على تخطيط واحد للمستخدم الذي سجل دخوله وآخر لأحد جوانب التسويق أو المبيعات في الموقع. قد يشمل تخطيط المستخدم المسجل على مستوى أعلى من التنقل يجب أن يكون موجودًا عبر العديد من إجراءات وحدة التحكم. قد يشمل تخطيط المبيعات لتطبيق SaaS مستوى تنقل أعلى لأشياء مثل صفحات "الأسعار" و"اتصل بنا". ينبغي أن تتوقع أن يكون لكل تخطيط شكل ومظهر مختلف. يمكنك القراءة عن التخطيطات بتفصيل أوسع في دليل [[Rails/layouts and rendering|التخطيطات والتصيير]].
+
يمكن استخدام التخطيطات (Layouts) لتصيير قالب عرض شائع حول نتائج Action Controller في ريلز. عادة، سيكون لتطبيق ريلز بعض التخطيطات التي ستُصيَّر هذه الصفحات ضمنها. على سبيل المثال، قد يحتوي أحد المواقع على تخطيط واحد للمستخدم الذي سجل دخوله وآخر لأحد جوانب التسويق أو المبيعات في الموقع. قد يشمل تخطيط المستخدم المسجل على مستوى أعلى من التنقل يجب أن يكون موجودًا عبر العديد من Action Controller. قد يشمل تخطيط المبيعات لتطبيق SaaS مستوى تنقل أعلى لأشياء مثل صفحات "الأسعار" و"اتصل بنا". ينبغي أن تتوقع أن يكون لكل تخطيط شكل ومظهر مختلف. يمكنك القراءة عن التخطيطات بتفصيل أوسع في دليل [[Rails/layouts and rendering|التخطيطات والتصيير]].
  
 
== تخطيطات الجزئية ==
 
== تخطيطات الجزئية ==
يمكن أن يكون للجزئيات (Partials) تخطيطات خاصة بهم مطبقة عليهم فقط. تختلف هذه التخطيطات عن تلك التي تُطَبَّق على إجراء وحدة التحكم، ولكنها تعمل بطريقة مماثلة.
+
يمكن أن يكون للجزئيات (Partials) تخطيطات خاصة بهم مطبقة عليهم فقط. تختلف هذه التخطيطات عن تلك التي تُطَبَّق على Action Controller، ولكنها تعمل بطريقة مماثلة.
  
 
لنفترض أننا نعرض مقالة على صفحة يجب أن تكون موجودة في <code>[[HTML/div|<nowiki><div></nowiki>]]</code> لأغراض العرض. أولًا، سننشئ مقالة <code>Article</code> جديدة:<syntaxhighlight lang="rails">
 
لنفترض أننا نعرض مقالة على صفحة يجب أن تكون موجودة في <code>[[HTML/div|<nowiki><div></nowiki>]]</code> لأغراض العرض. أولًا، سننشئ مقالة <code>Article</code> جديدة:<syntaxhighlight lang="rails">
سطر 228: سطر 228:
 
يمكننا القيام بذلك باستخدام:<syntaxhighlight lang="rails">
 
يمكننا القيام بذلك باستخدام:<syntaxhighlight lang="rails">
 
prepend_view_path "app/views/#{request.subdomain}"
 
prepend_view_path "app/views/#{request.subdomain}"
</syntaxhighlight>بعد ذلك، سيظهر إجراء العرض أولًا في هذا المجلد عند استبيان العروض.
+
</syntaxhighlight>بعد ذلك، سيظهر Action View أولًا في هذا المجلد عند استبيان العروض.
  
 
=== إضافة لاحقة لمسار العرض ===
 
=== إضافة لاحقة لمسار العرض ===
سطر 235: سطر 235:
 
</syntaxhighlight>سيضيف هذا المسار app/views/direct إلى نهاية مسارات البحث (lookup paths).
 
</syntaxhighlight>سيضيف هذا المسار app/views/direct إلى نهاية مسارات البحث (lookup paths).
  
== نظرة عامة على المساعدين الذين يوفرهم إجراء العرض ==
+
== نظرة عامة على المساعدين الذين يوفرهم Action View ==
 
'''قيد العمل''': ليس جميع المساعدين مذكورون هنا. للاطلاع على قائمة المساعدين الكاملة، انتقل إلى [http://api.rubyonrails.org/v5.2.2/classes/ActionView/Helpers.html توثيق الواجهة البرمجية].
 
'''قيد العمل''': ليس جميع المساعدين مذكورون هنا. للاطلاع على قائمة المساعدين الكاملة، انتقل إلى [http://api.rubyonrails.org/v5.2.2/classes/ActionView/Helpers.html توثيق الواجهة البرمجية].
  
ما يلي هو ملخص قصير للمساعدين المتوفرين في إجراء العرض. يوصى بمراجعة [http://api.rubyonrails.org/v5.2.2/classes/ActionView/Helpers.html توثيق الواجهة البرمجية]، التي تغطي جميع المساعدين بمزيد من التفصيل، ولكن يجب أن يكون هذا بمثابة نقطة بداية جيدة.
+
ما يلي هو ملخص قصير للمساعدين المتوفرين في Action View. يوصى بمراجعة [http://api.rubyonrails.org/v5.2.2/classes/ActionView/Helpers.html توثيق الواجهة البرمجية]، التي تغطي جميع المساعدين بمزيد من التفصيل، ولكن يجب أن يكون هذا بمثابة نقطة بداية جيدة.
  
 
=== المساعد <code>AssetTagHelper</code> ===
 
=== المساعد <code>AssetTagHelper</code> ===
سطر 488: سطر 488:
  
 
==== <code>time_select</code> ====
 
==== <code>time_select</code> ====
يعيد مجموعة من وسوم اختيار (select tags، واحد للساعة وواحد للدقيقة وواحد للثانية اختياريًا) محددة مسبقًا للدخول إلى خاصية محددة تستند إلى الوقت. تُعد الاختيارات لتعيين معاملات متعددة إلى كائن [[Rails/active record basics|سجل فعال]].<syntaxhighlight lang="rails">
+
يعيد مجموعة من وسوم اختيار (select tags، واحد للساعة وواحد للدقيقة وواحد للثانية اختياريًا) محددة مسبقًا للدخول إلى خاصية محددة تستند إلى الوقت. تُعد الاختيارات لتعيين معاملات متعددة إلى كائن [[Rails/active record basics|Active Record]].<syntaxhighlight lang="rails">
 
# submitted في الخاصية order توليد حقل اختيار وقت سيخزن عند إرساله في المتغير
 
# submitted في الخاصية order توليد حقل اختيار وقت سيخزن عند إرساله في المتغير
 
time_select("order", "submitted")
 
time_select("order", "submitted")
سطر 774: سطر 774:
  
 
=== المساعد <code>FormTagHelper</code> ===
 
=== المساعد <code>FormTagHelper</code> ===
يوفر عددًا من التوابع لإنشاء وسوم [[HTML/form|النموذج]] التي لا تعتمد على كائن [[Rails/active record basics|السجل الفعال]] المعين إلى القالب مثل <code>FormHelper</code>. بدلًا من ذلك، يمكنك تقديم الأسماء والقيم يدويًا.
+
يوفر عددًا من التوابع لإنشاء وسوم [[HTML/form|النموذج]] التي لا تعتمد على كائن [[Rails/active record basics|Active Record]] المعين إلى القالب مثل <code>FormHelper</code>. بدلًا من ذلك، يمكنك تقديم الأسماء والقيم يدويًا.
  
 
==== <code>check_box_tag</code> ====
 
==== <code>check_box_tag</code> ====
سطر 803: سطر 803:
  
 
==== <code>form_tag</code> ====
 
==== <code>form_tag</code> ====
يبدأ وسم [[HTML/form|نموذج]] بتوجيه الإجراء إلى عنوان URL هُيِّئ باستخدام <code>url_for_options</code> تمامًا مثل <code>ActionController::Base#url_for</code>.<syntaxhighlight lang="html">
+
يبدأ وسم [[HTML/form|نموذج]] بتوجيه الإجراء إلى عنوان URL هُيِّئ باستخدام <code>url_for_options</code> تمامًا مثل <code>ActionController::Base.url_for</code>.<syntaxhighlight lang="html">
 
<%= form_tag '/articles' do %>
 
<%= form_tag '/articles' do %>
 
   <div><%= submit_tag 'Save' %></div>
 
   <div><%= submit_tag 'Save' %></div>
سطر 983: سطر 983:
  
 
== عروض متعلقة بالمحليَّة ==
 
== عروض متعلقة بالمحليَّة ==
يحوي إجراء العرض على قابلية عرض قوالب مختلفة استنادًا إلى الإعدادات المحلية (locale) الحالية.
+
يحوي Action View على قابلية عرض قوالب مختلفة استنادًا إلى الإعدادات المحلية (locale) الحالية.
  
على سبيل المثال، افترض أن لديك المتحكم <code>MaterialController</code> مع إجراء عرض. بشكل افتراضي، استدعاء هذا الإجراء سيصيِّر العرض app/views/articles/show.html.erb. ولكن إذا ضبطت المحلية بالشكل <code>I18n.locale = :de</code>، فسيصيِّر العرض app/views/articles/show.de.html.erb بدلًا من ذلك. إذا كان القالب الخاص بالمحلية (المحلية de هنا) غير موجود، فستُستخدًم النسخة غير المزخرفة. هذا يعني أنك لست مطالبًا بتقديم عروض متعلقة بالمحلية لجميع الحالات، ولكن ستُفضَّل وتُستخدَم إذا كانت متوافرة.
+
على سبيل المثال، افترض أن لديك المتحكم <code>MaterialController</code> مع Action View. بشكل افتراضي، استدعاء Action View هذا سيصيِّر العرض app/views/articles/show.html.erb. ولكن إذا ضبطت المحلية بالشكل <code>I18n.locale = :de</code>، فسيصيِّر العرض app/views/articles/show.de.html.erb بدلًا من ذلك. إذا كان القالب الخاص بالمحلية (المحلية de هنا) غير موجود، فستُستخدًم النسخة غير المزخرفة. هذا يعني أنك لست مطالبًا بتقديم عروض متعلقة بالمحلية لجميع الحالات، ولكن ستُفضَّل وتُستخدَم إذا كانت متوافرة.
  
 
يمكنك استخدام نفس التقنية لتخصيص ملفات الإنقاذ (rescue files) في المجلد العام بناءً على قيمة المحلية. على سبيل المثال، ضبط <code>I18n.locale = :de</code> وإنشاء public/500.de.html و public/404.de.html يسمح لك بعرض صفحات الإنقاذ بما يتوافق مع قيمة المحلية المضبوطة، التي هي de في حالتنا هذه.
 
يمكنك استخدام نفس التقنية لتخصيص ملفات الإنقاذ (rescue files) في المجلد العام بناءً على قيمة المحلية. على سبيل المثال، ضبط <code>I18n.locale = :de</code> وإنشاء public/500.de.html و public/404.de.html يسمح لك بعرض صفحات الإنقاذ بما يتوافق مع قيمة المحلية المضبوطة، التي هي de في حالتنا هذه.

مراجعة 07:25، 20 مارس 2019

بعد قراءة هذا الدليل، ستعرف:

  • ما هو Action View وكيفية استخدامه مع ريلز.
  • أفضل طريقة لاستخدام القوالب والجزئيات (partials) والتخطيطات.
  • ما الذي يقدمه المساعدون عن طريق Action View.
  • كيفية استخدام العروض المحلية.

ما هو Action View؟

في ريلز، تُعَالَج طلبات الويب من خلال Action Controller و Action View. عادةً ما يقع على عاتق وحدة التحكم التواصل مع قاعدة البيانات وتنفيذ الإجراءات CRUD عند الضرورة؛ بعد ذلك، يكون Action View مسؤولًا عن تفسير (compiling) الاستجابة.

تُكتَب قوالب Action View باستخدام روبي المضمّنة بالوسوم التي تمزج مع HTML. لتجنب ازدحام القوالب بشيفرة نمطية، يوفر عدد من أصناف المساعد سلوكًا شائعًا للنماذج والتواريخ والسلاسل النصية. من السهل أيضًا إضافة مساعدين جدد إلى تطبيقك أثناء تطويره.

ملاحظة: ترتبط بعض ميزات Action View بـ Active Record، ولكن هذا لا يعني أن Action View يعتمد على Active Record. إنَّ Action View هو حزمة مستقلة يمكن استخدامها مع أي نوع من مكتبات روبي.

استخدام Action View مع ريلز

هناك مجلد مرتبط في المجلد app/views لكل وحدة تحكم الذي يحتفظ بملفات القالب التي تشكل العروض المرتبطة بوحدة التحكم هذه. تُستخدَم هذه الملفات لعرض الشكل التي تنتج من كل Action Controller.

دعنا نلقي نظرة على ما يفعله ريلز افتراضيَّا عند إنشاء مصدر جديد باستخدام المولد Scaffold:

$ bin/rails generate scaffold article
      [...]
      invoke  scaffold_controller
      create    app/controllers/articles_controller.rb
      invoke    erb
      create      app/views/articles
      create      app/views/articles/index.html.erb
      create      app/views/articles/edit.html.erb
      create      app/views/articles/show.html.erb
      create      app/views/articles/new.html.erb
      create      app/views/articles/_form.html.erb
      [...]

يوجد اصطلاح تسمية للعروض في ريلز. عادةً ما تشارك العروض اسمَها مع Action Controller المرتبط، كما ترى أعلاه. على سبيل المثال، سيستخدم فهرس حدث وحدة التحكم article_controller.rb ملف العرض index.html.erb في المجلد app/views/articles. الملف HTML الكامل المعاد إلى العميل يتكون من مزيج من الملف ERB هذا، وقالب تخطيط يغلفه، وكل الجزئيات (partials) التي يشير إليها العرض. ضمن هذا الدليل، ستجد توثيقًا أكثر تفصيلًا حول كل من هذه المكونات الثلاثة.

القوالب والجزئيات والتخطيطات

كما ذكرنا، فإن ناتج HTML النهائي هو عبارة عن تركيبة تتألف من ثلاثة عناصر هي: القوالب والجزئيات والتخطيطات. فيما يلي نظرة عامة موجزة لكل منها.

القوالب

يمكن كتابة قوالب Action View بعدة طرق. إذا كان ملف القالب بامتداد erb.، فإنه يستخدم خليطًا من ERB (روبي المضمَّنة [Embedded Ruby]) و HTML. إذا كان ملف القالب بامتداد builder.، فستُستخدَم المكتبة Builder::XmlMarkup.

يدعم ريلز أنظمة القوالب المتعددة ويستخدم امتدادًا للملف للتمييز بينها. على سبيل المثال، يملك الملف HTML المستخدِم لنظام القالب ERB الامتداد html.erb. كامتداد للملف.

القالب ERB

داخل قالب ERB، يمكن تضمين شيفرة روبي باستخدام الوسم <% %> والوسم ‎<%= %>‎. تُستخدَم الوسوم <% %> لتنفيذ شيفرة روبي التي لا تعيد شيئًا، مثل الشروط أو الحلقات التكرارية أو الكُتَل، وتُستخدَم الوسوم ‎<%= %>‎ عندما تريد الحصول على مخرجات من الشيفرة.

تأمل الحلقة التكرارية التالية للأسماء:

<h1>Names of all the people</h1>
<% @people.each do |person| %>
  Name: <%= person.name %><br>
<% end %>

تنفَّذ الحلقة التكرارية باستخدام وسوم التضمين العادية (<% %>) ويُدرَج الاسم في ملف HTML باستخدام وسوم تضمين المخرجات (‎<%= %>‎). لاحظ أن هذا ليس مجرد اقتراح للاستخدام: لن تصيَّر دوال الإخراج العادية مثل print و puts في العرض باستخدام قوالب ERB. لذلك، ستكون الشيفرة التالية خطأً:

<%# WRONG %>
Hi, Mr. <% puts "Frodo" %>

لإزالة المسافات البيضاء السابقة واللاحقة، يمكنك استخدام <%- -%> بدلًا من <% و %>.

Builder

القوالب Builder بديل أكثر قابلية للبرمجة عن القوالب ERB، وهي مفيدة بشكل خاص لتوليد محتوى XML. يُتَاح الكائن XmlMarkup المسمى xml تلقائيًا للقوالب ذات الامتداد builder..

هُنا بعض الأمثلة الأساسية:

xml.em("emphasized")
xml.em { xml.b("emph & bold") }
xml.a("A Link", "href" => "http://rubyonrails.org")
xml.target("name" => "compile", "option" => "fast")

التي تُنتِج:

<em>emphasized</em>
<em><b>emph &amp; bold</b></em>
<a href="http://rubyonrails.org">A link</a>
<target option="fast" name="compile" />

سيُتَعامَل مع أي دالة تحوي كتلةً كوسم ترميز XML مع ترميز متداخل في الكتلة. على سبيل المثال، ما يلي:

xml.div {
  xml.h1(@person.name)
  xml.p(@person.bio)
}

قد ينتج شيئًا مثل:

<div>
  <h1>David Heinemeier Hansson</h1>
  <p>A product of Danish Design during the Winter of '79...</p>
</div>

فيما يلي مثال RSS كامل الطول مستخدم فعليًا في Basecamp:

xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
  xml.channel do
    xml.title(@feed_title)
    xml.link(@url)
    xml.description "Basecamp: Recent items"
    xml.language "en-us"
    xml.ttl "40"
 
    for item in @recent_items
      xml.item do
        xml.title(item_title(item))
        xml.description(item_description(item)) if item_description(item)
        xml.pubDate(item_pubDate(item))
        xml.guid(@person.firm.account.url + @recent_items.url(item))
        xml.link(@person.firm.account.url + @recent_items.url(item))
        xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
      end
    end
  end
end

Jbuilder

إن قوالب Jbuilder عبارة عن جوهرة يُحسِّنُها فريق ريلز وتُضمَّن في Gemfile الافتراضي الخاص بريلز. هذه القوالب مشابهة للقوالب Builder، ولكنها تُستخدم لإنشاء JSON، بدلًا من XML.

إذا لم تملك هذه الجوهرة، يمكنك إضافتها إلى Gemfile بتنفيذ السطر التالي:

gem 'jbuilder'

يُتَاح كائن Jbuilder المسمى json تلقائيًا للقوالب ذات الامتداد jbuilder.. هنا مثال أساسي:

json.name("Alex")
json.email("alex@example.com")

ستُنتِج:

{
  "name": "Alex",
  "email": "alex@example.com"
}

راجع توثيق Jbuilder لمزيد من الأمثلة والمعلومات.

قالب التخزين المؤقت

بشكل افتراضي، ستُصرِّف ريلز كل قالب إلى دالة لتصييره وعرضه. عندما تُغيِّر قالبًا، سيفحص ريلز وقت تعديل الملف ويُعيد تصريفه في وضع التطوير.

الجزئيات

القوالب الجزئية (Partial templates) -تسمى "الجزئيات" (partials) عادةً- هي أداة أخرى لكسر عملية التصير إلى أجزاء أكثر قابلية للإدارة. باستخدام الجزئيات، يمكنك استخراج أجزاء من الشيفرة البرمجية من قوالبك لفصل الملفات وإعادة استخدامها أيضًا في جميع القوالب.

تسمية الجزئيات

لتصيير جزئية بفرض أنها جزءٌ من عرض، استخدم التابع render ضمن العرض:

<%= render "menu" %>

سيصيّر هذا ملفًا باسم menu.html.erb_ في تلك النقطة داخل العرض الذي يصيَّر. لاحظ الشَرطة البادئة السفلية؛ تُسمَّى الجزئيات باستخدام شرطة بادئة سفلية لتمييزها عن العروض العادية، حتى لو أُشِير إليها بدون شَرطة سُفلية. هذا صحيح حتى عند سحب جزئية من مجلد آخر:

<%= render "shared/menu" %>

ستسحب هذه الشيفرة في الجزئية من app/views/shared/_menu.html.erb.

استخدام الجزئيات لتبسيط العروض

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

<%= render "shared/ad_banner" %>
 
<h1>Products</h1>
 
<p>Here are a few of our fine products:</p>
<% @products.each do |product| %>
  <%= render partial: "product", locals: { product: product } %>
<% end %>
 
<%= render "shared/footer" %>

هنا، يمكن أن تحتوي الجزئيتان ‎_ad_banner.html.erb و ‎_footer.html.erb على محتوى يُشارَك بين العديد من الصفحات في تطبيقك. لست بحاجة إلى الاطلاع على تفاصيل هذه الأقسام عند التركيز على صفحة معينة.

تصيير بدون الخيارين partial و locals

في المثال أعلاه، يأخذ render خيارين هما: partial و locals. ولكن إذا كان هذان الخياران هما الخيارين اللذين تريد استعمالهما، فيمكنك تخطي استخدامهما ببساطة. على سبيل المثال، بدلًا من:

<%= render partial: "product", locals: { product: @product } %>

يمكنك أيضًا فِعل ما يلي:

<%= render "product", product: @product %>

الخياران as و object

بشكل افتراضي، يحتوي ActionView::Partials::PartialRenderer على كائنه الخاص في متغير محلي بنفس الاسم مثل القالب. لذلك، كتابة:

<%= render partial: "product" %>

ضمن الجزئية ‎_product سيؤدي إلى الحصول على product@ في المتغير المحلي product؛ أي كما لو أننا قد كتبنا:

<%= render partial: "product", locals: { product: @product } %>

يمكن استخدام الخيار object لتحديد الكائن الذي يُعرَض مباشرة داخل الجزئية، وهو مفيد عندما يكون كائن القالب في مكان آخر (على سبيل المثال في متغير نسخة مختلف أو في متغير محلي). على سبيل المثال، بدلًا من كتابة:

<%= render partial: "product", locals: { product: @item } %>

سنكتب:

<%= render partial: "product", object: @item %>

مع الخيار as، يمكننا تحديد اسم مختلف للمتغير المحلي المذكور. على سبيل المثال، إذا أردنا أن يكون item بدلًا من product، فسنكتب ما يلي:

<%= render partial: "product", object: @item, as: "item" %>

هذا يعادل:

<%= render partial: "product", locals: { item: @item } %>

تصيير المجموعات

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

<% @products.each do |product| %>
  <%= render partial: "product", locals: { product: product } %>
<% end %>

يمكن إعادة كتابته في سطر واحد:

<%= render partial: "product", collection: @products %>

عند استدعاء جزئية ما مع مجموعة، تملك النسخ الفردية للجزئية حق الوصول إلى عضو المجموعة الذي يُصيَّر عبر متغير مسمى بعد الجزئية. في هذه الحالة، الجزئية هي product_، وضمنها يمكنك الرجوع إلى المنتج product للحصول على عضو المجموعة الذي يُصيَّر. يمكنك استخدام صيغة مختصرة لتصيير المجموعات. بافتراض أن ‎@products عبارة عن مجموعة من النسخ product، يمكنك ببساطة كتابة ما يلي لتوليد النتيجة نفسها:

<%= render @products %>

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

قوالب فاصلة

يمكنك أيضًا تحديد جزئية ثانية لتصييرها بين نسخ الجزئية الرئيسية باستخدام الخيار ‎:spacer_template:

<%= render partial: @products, spacer_template: "product_ruler" %>

سيصيِّر ريلز الجزئية product_ruler_ (مع عدم تمرير بيانات إليها) بين كل زوج من جزئيات product_.

التخطيطات

يمكن استخدام التخطيطات (Layouts) لتصيير قالب عرض شائع حول نتائج Action Controller في ريلز. عادة، سيكون لتطبيق ريلز بعض التخطيطات التي ستُصيَّر هذه الصفحات ضمنها. على سبيل المثال، قد يحتوي أحد المواقع على تخطيط واحد للمستخدم الذي سجل دخوله وآخر لأحد جوانب التسويق أو المبيعات في الموقع. قد يشمل تخطيط المستخدم المسجل على مستوى أعلى من التنقل يجب أن يكون موجودًا عبر العديد من Action Controller. قد يشمل تخطيط المبيعات لتطبيق SaaS مستوى تنقل أعلى لأشياء مثل صفحات "الأسعار" و"اتصل بنا". ينبغي أن تتوقع أن يكون لكل تخطيط شكل ومظهر مختلف. يمكنك القراءة عن التخطيطات بتفصيل أوسع في دليل التخطيطات والتصيير.

تخطيطات الجزئية

يمكن أن يكون للجزئيات (Partials) تخطيطات خاصة بهم مطبقة عليهم فقط. تختلف هذه التخطيطات عن تلك التي تُطَبَّق على Action Controller، ولكنها تعمل بطريقة مماثلة.

لنفترض أننا نعرض مقالة على صفحة يجب أن تكون موجودة في <div> لأغراض العرض. أولًا، سننشئ مقالة Article جديدة:

Article.create(body: 'Partial Layouts are cool!')

في قالب العرض، سنعرض الجزئية article_ في تخطيط صندوقي (box layout): الملف articles/show.html.erb

<%= render partial: 'article', layout: 'box', locals: { article: @article } %>

التخطيط الصندوقي ببساطة يلف الجزئية article_ في عنصر <div>: الملف articles/_box.html.erb

<div class='box'>
  <%= yield %>
</div>

لاحظ أن تخطيط الجزئية يمكنه الوصول إلى المتغير article المحلي الذي مُرِّر عند استدعاء render. ومع ذلك، على عكس التخطيطات التي على مستوى التطبيق، لا تزال التخطيطات الجزئية تحتوي على بادئة سُفلية.

يمكنك أيضًا تصيير كتلة من الشيفرة داخل تخطيط جزئية بدلًا من استدعاء yield. على سبيل المثال، إذا لم تكن لدينا الجزئية article_، فيمكننا القيام بما يلي بدلًا من ذلك:

الملف articles/show.html.erb

<% render(layout: 'box', locals: { article: @article }) do %>
  <div>
    <p><%= article.body %></p>
  </div>
<% end %>

لنفترض أننا نستخدم الجزئية ‎_box نفسها مما سبق، فإن هذا سيولد نفس الناتج المولد من المثال السابق.

مسارات العرض

عند تصيير استجابة، تحتاج وحدة التحكم إلى تحديد مكان وجود العروض المختلفة. بشكل افتراضي، سيُنظر فقط داخل المجلد app/views.

يمكننا إضافة مواقع أخرى ومنحهم أولوية معينة عند استبيان المسارات باستخدام التابعين prepend_view_path و append_view_path.

إضافة سابقة لمسار العرض

يمكن أن يكون هذا مفيدًا على سبيل المثال، عندما نريد وضع العروض داخل مجلد مختلف عن النطاقات الفرعية.

يمكننا القيام بذلك باستخدام:

prepend_view_path "app/views/#{request.subdomain}"

بعد ذلك، سيظهر Action View أولًا في هذا المجلد عند استبيان العروض.

إضافة لاحقة لمسار العرض

وبالمثل، يمكننا إضافة لاحقة للمسارات بالشكل التالي:

append_view_path "app/views/direct"

سيضيف هذا المسار app/views/direct إلى نهاية مسارات البحث (lookup paths).

نظرة عامة على المساعدين الذين يوفرهم Action View

قيد العمل: ليس جميع المساعدين مذكورون هنا. للاطلاع على قائمة المساعدين الكاملة، انتقل إلى توثيق الواجهة البرمجية.

ما يلي هو ملخص قصير للمساعدين المتوفرين في Action View. يوصى بمراجعة توثيق الواجهة البرمجية، التي تغطي جميع المساعدين بمزيد من التفصيل، ولكن يجب أن يكون هذا بمثابة نقطة بداية جيدة.

المساعد AssetTagHelper

يوفر هذا النموذج دوالًّا لتوليد شيفرة HTML تربط العروض بالأصول (assets) مثل الصور وملفات جافاسكربت وملفات الأنماط وقارئي التغذية (feed readers).

بشكل افتراضي، يقترن ريلز بهذه الأصول على الاستضافة الحالية في المجلد العام، ولكن يمكنك توجيه ريلز للربط بالأصول من خادم أصول مخصص عن طريق تعيين config.action_controller.asset_host في تكوين التطبيق، عادةً في الملف config/environments/production.rb. على سبيل المثال، لنفترض أن استضافة الأصول لديك هي assets.example.com:

config.action_controller.asset_host = "assets.example.com"
image_tag("rails.png") # => <img src="http://assets.example.com/images/rails.png" />

auto_discovery_link_tag

يعيد وسم رابط يمكن للمتصفحات وقارئي التغذية (feed readers) استخدامها للاكتشاف التلقائي لتغذية RSS أو Atom أو JSON.

auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", { title: "RSS Feed" }) # =>
  <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed.rss" />

image_path

يَحسب المسار إلى أصل الصورة في المجلد app/assets/images. ستُمرر المسارات الكاملة من جذر المستند. يُستخدم داخليًا بواسطة image_tag لبناء مسار الصورة.

image_path("edit.png") # => /assets/edit.png

ستُضاف بصمة (fingerprint) إلى اسم الملف إذا ضُبِطَ config.assets.digest إلى القيمة true.

image_path("edit.png") # => /assets/edit-2d1a2db63fc738690021fedb5a65b68e.png

image_url

يَحسب عنوان URL لأصل الصورة في المجلد app/assets/images. سيستدعي هذا التابع image_path داخليًا ويدمجه مع استضافتك الحالية أو استضافة الأصول.

image_url("edit.png") # => http://www.example.com/assets/edit.png

image_tag

يعيد وسم HTML للصورة للمصدر. يمكن أن يكون المصدر مسارًا كاملًا أو ملفًا موجودًا في المجلد app/assets/images.

image_tag("icon.png") # => <img src="/assets/icon.png" />

javascript_include_tag

يعيد الوسم <script> لكل من المصادر المعطاة. يمكنك تمرير اسم الملف (تحديد الامتداد ‎.js اختياري) لملفات JavaScript الموجودة في المجلد app/assets/javascripts لتضمينها في الصفحة الحالية أو يمكنك تمرير المسار الكامل المتعلق بجذر المستند.

javascript_include_tag "common" # => <script src="/assets/common.js"></script>

javascript_path

يحسب المسار إلى أصل جافاسكربت في المجلد app/assets/javascripts. إذا لم يحتو اسم الملف المصدر على امتداد، فسيُلحَق ‎.js. ستُمرَّر المسارات الكاملة من جذر المستند. يستخدم داخليًا بواسطة javascript_include_tag لإنشاء مسار شيفرة مكتوبة بلغة جافاسكربت.

javascript_path "common" # => /assets/common.js

javascript_url

يحسب عنوان URL لأصل جافاسكربت في المجلد app/assets/javascripts. سيستدعي هذا التابع  javascript_path داخليًا ويدمجه مع استضافتك الحالية أو استضافة الأصول.

javascript_url "common" # => http://www.example.com/assets/common.js

stylesheet_link_tag

يعيد وسم رابط ورقة أنماط للمصادر المحددة كوسائط. إذا لم تحدد لاحقة، فستستعمل اللاحقة ‎.css تلقائيًا.

stylesheet_link_tag "application" # => <link href="/assets/application.css" media="screen" rel="stylesheet" />

stylesheet_path

يحسب المسار إلى أصل ورقة الأنماط في المجلد app/assets/stylesheets. إذا لم يحتوِ اسم الملف المصدر على لاحقة، فستستعمل اللاحقة ‎.css. ستُمرَّر المسارات الكاملة من جذر المستند. يُستخدَم داخليًا بواسطة stylesheet_link_tag لإنشاء مسار ورقة الأنماط.

stylesheet_path "application" # => /assets/application.css

stylesheet_url

يحسب عنوان URL لأصل ورقة أنماط في المجلد app/assets/stylesheets. سيستدعي هذا التابع stylesheet_path داخليًا ويدمجه مع استضافتك الحالية أو استضافة الأصول.

stylesheet_url "application" # => http://www.example.com/assets/application.css

المساعد AtomFeedHelper

atom_feed

يجعل هذا المساعد بناء تغذية Atom عمليةً سهلةً. إليك مثال كامل عن كيفية الاستخدام:

الملف config/routes.rb

resources :articles

الملف app/controllers/articles_controller.rb

def index
  @articles = Article.all
 
  respond_to do |format|
    format.html
    format.atom
  end
end

الملف app/views/articles/index.atom.builder

atom_feed do |feed|
  feed.title("Articles Index")
  feed.updated(@articles.first.created_at)
 
  @articles.each do |article|
    feed.entry(article) do |entry|
      entry.title(article.title)
      entry.content(article.body, type: 'html')
 
      entry.author do |author|
        author.name(article.author_name)
      end
    end
  end
end

المساعد BenchmarkHelper

benchmark

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

<% benchmark "Process data files" do %>
  <%= expensive_files_operation %>
<% end %>

هذا من شأنه أن يضيف شيئًا مثل "Process data files (0.34523)‎" إلى السجل، والذي يمكنك استخدامه حينئذٍ لمقارنة الوقت الذي تستغرقه العملية مما يساعد على تحسين الأداء.

المساعد CacheHelper

cache

دالة للتخزين المؤقت لأجزاء من العرض بدلًا من كامل الإجراء أو الصفحة. هذه التقنية مفيدة للتخزين المؤقت مثل القوائم وقوائم مواضيع الأخبار وأجزاء من شيفرة HTML الثابتة وما إلى ذلك. تأخذ هذه دالة كتلة تحتوي على المحتوى الذي تريد تخزينه مؤقتًا. انظر AbstractController::Caching::Fragments لمزيد من المعلومات.

<% cache do %>
  <%= render "shared/footer" %>
<% end %>

المساعد CaptureHelper

capture

يتيح لك التابع capture استخراج جزء من القالب إلى متغير. يمكنك بعد ذلك استخدام هذا المتغير في أي مكان ما في قوالبك أو تخطيطاتك.

<% @greeting = capture do %>
  <p>Welcome! The date and time is <%= Time.now %></p>
<% end %>

يمكن استخدام المتغير الذي ألتُقِط في أي مكان آخر.

<html>
  <head>
    <title>Welcome!</title>
  </head>
  <body>
    <%= @greeting %>
  </body>
</html>

content_for

استدعاء التابع content_for يخزن كتلة من الشيفرة في مُعرِّف لاستخدامها لاحقًا. يمكنك إجراء استدعاءات متلاحقة للمحتوى المخزن في قوالب أخرى أو في المخطط بتمرير المعرف كوسيط إلى yield.

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

الملف app/views/layouts/application.html.erb

<html>
  <head>
    <title>Welcome!</title>
    <%= yield :special_script %>
  </head>
  <body>
    <p>Welcome! The date and time is <%= Time.now %></p>
  </body>
</html>

الملف app/views/articles/special.html.erb

<p>This is a special page.</p>
 
<% content_for :special_script do %>
  <script>alert('Hello!')</script>
<% end %>

المساعد DateHelper

date_select

يعيد مجموعة من وسوم التحديد (واحد للسنة وواحد للشهر وواحد لليوم) المحددة مسبقًا للوصول إلى خاصية محددة تستند إلى التاريخ.

date_select("article", "published_on")

datetime_select

يعيد مجموعة من وسوم التحديد (واحد للسنة وواحد للشهر وواحد لليوم وواحد للساعة وواحد للدقيقة) محددة مسبقًا للوصول إلى خاصية محددة على أساس التاريخ والوقت.

datetime_select("article", "published_on")

distance_of_time_in_words

يُعد تقارير المسافة التقريبية في الوقت بين الكائنين Time أو Date أو بين أعداد صحيحة في واحدة الثانية. اضبِط include_seconds إلى القيمة true إذا كنت ترغب في الحصول على تقديرات تقريبية أكثر تفصيلًا.

distance_of_time_in_words(Time.now, Time.now + 15.seconds)        # => less than a minute
distance_of_time_in_words(Time.now, Time.now + 15.seconds, include_seconds: true)  # => less than 20 seconds

select_date

يعيد مجموعة من وسوم اختيار HTML (واحد للسنة وواحد للشهر وواحد لليوم) محددة مسبقًا مع التاريخ المعطى.

# توليد اختيار تاريخ معين افتراضيًّا إلى التاريخ المعطى (ستة أيام بعد تاريخ اليوم)
select_date(Time.today + 6.days)
 
# توليد اختيار تاريخ معين افتراضيًا إلى تاريخ اليوم
select_date()

select_datetime

يعيد مجموعة من وسوم اختيار HTML (واحد للسنة وواحد للشهر وواحد لليوم وواحد للساعة وواحد للدقيقة) محددة مسبقًا مع التاريخ والوقت المعطى.

# توليد اختيار تاريخ ووقت معينين افتراضيًا إلى القيمة المعطاة (أربعة أيام من اليوم)
select_datetime(Time.now + 4.days)
 
# توليد اختيار تاريخ ووقت معينين افتراضيًا إلى اليوم
select_datetime()

select_day

يعيد وسم اختيار يحتوي على خيارات لكل يوم من الأيام من 1 إلى 31 مع تحديد اليوم الحالي.

# توليد حقل اختيار من أجل الأيام معين افتراضيًا إلى اليوم في التاريخ المعطى
select_day(Time.today + 2.days)
 
# توليد حقل اختيار من أجل الأيام معين افتراضيًا إلى الرقم المعطى
select_day(5)

select_hour

يعيد وسم اختيار يحتوي على خيارات لكل ساعة من الساعات من 0 إلى 23 مع تحديد الساعة الحالية.

# توليد حقل اختيار من أجل الساعات يعين افتراضيًا إلى الساعات في الوقت المعطى
select_hour(Time.now + 6.hours)

select_minute

يعيد وسم اختيار يحتوي على خيارات لكل من الدقائق من 0 إلى 59 مع تحديد الدقيقة الحالية.

# توليد حقل اختيار من أجل الدقائق معين افتراضيًا إلى الدقائق في الوقت المعطى
select_minute(Time.now + 10.minutes)

select_month

يعيد وسم اختيار يحتوي على خيارات لكل من الأشهر من يناير حتى ديسمبر مع تحديد الشهر الحالي.

# توليد حقل اختيار من أجل الأشهر يعين افتراضيًا إلى الشهر الحالي
select_month(Date.today)

select_second

يعيد وسم اختيار يحتوي على خيارات لكل ثانية من الثواني من 0 إلى 59 مع تحديد الثاني الحالي.

# توليد حقل اختيار من أجل الثواني يعين افتراضيًا إلى الثواني في الوقت المعطى
select_second(Time.now + 16.seconds)

select_time

يعيد مجموعة من وسوم اختيار HTML (واحد للساعة وواحد للدقيقة).

# توليد حقل اختيار من أجل الوقت يعين افتراضيًا إلى الوقت المعطى
select_time(Time.now)

select_year

يعيد وسم اختيار مع خيارات لكل من السنوات الخمس على كل جانب من السنة الحالية، أو المحددة. يمكن تغيير نصف قطر الخمس سنوات باستخدام ‎:start_year و ‎:end_year في الخيارات.

# توليد حقل اختيار من أجل خمس سنوات على كلا جانبي تاريخ اليوم
# الذي يعين افتراضيًا إلى السنة الحالية
select_year(Date.today)
 
# توليد حقل اختيار من 1900 إلى 2009 يعين افتراضيًا إلى السنة الحالية
select_year(Date.today, start_year: 1900, end_year: 2009)

time_ago_in_words

يشبه التابع distance_of_time_in_words باستثناء أنه يضبط to_time إلى Time.now.

time_ago_in_words(3.minutes.from_now)  # => 3 minutes

time_select

يعيد مجموعة من وسوم اختيار (select tags، واحد للساعة وواحد للدقيقة وواحد للثانية اختياريًا) محددة مسبقًا للدخول إلى خاصية محددة تستند إلى الوقت. تُعد الاختيارات لتعيين معاملات متعددة إلى كائن Active Record.

# submitted في الخاصية order توليد حقل اختيار وقت سيخزن عند إرساله في المتغير
time_select("order", "submitted")

المساعد DebugHelper

يعيد الوسم <pre> به كائن فُرِّغَ بواسطة YAML. يُنشِئ هذا طريقةً سهلة القراءة لفحص كائن.

my_hash = { 'first' => 1, 'second' => 'two', 'third' => [1,2,3] }
debug(my_hash)
<pre class='debug_dump'>---
first: 1
second: two
third:
- 1
- 2
- 3
</pre>

المساعد FormHelper

صُمِّمَ مساعدو النماذج لجعل العمل مع النماذج أسهل بكثير مقارنة باستخدام عناصر HTML القياسية فقط من خلال توفير مجموعة من الدوال لإنشاء النماذج استنادًا إلى نماذجك (models). يولد هذا المساعد شيفرة HTML للنماذج، ويوفر طريقة لكل نوع من أنواع عناصر الإدخال (مثل نص، وكلمة المرور، وحقل اختيار، وما إلى ذلك). عند إرسال النموذج (أي عندما يضغط المستخدم على زر الإرسال أو تُستدعَى form.submit عبر جافاسكربت) ، ستُجمع مدخلات النموذج في كائن المعاملات ثم تُعاد إلى وحدة التحكم.

هناك نوعان من مساعدي النموذج: أولئك الذين يعملون تحديدًا مع خصائص النموذج وتلك التي لا تعمل. يتعامل هذا المساعد مع تلك التي تعمل مع خصائص النموذج. لمشاهدة مثال على مساعدي النموذج الذين لا يعملون مع خصائص النموذج، راجع توثيق ActionView::Helpers::FormTagHelper.

تمنحك الدالة الأساسية لهذا المساعد، form_for، القدرة على إنشاء نموذج لنسخة نموذج (model)؛ على سبيل المثال، لنفترض أنك تمتلك النموذج Person وتريد إنشاء نسخة جديدة منه:

# (@person = Person.new في المتحكم (أي @person تنبيه: سيُنشَأ المتغير
<%= form_for @person, url: { action: "create" } do |f| %>
  <%= f.text_field :first_name %>
  <%= f.text_field :last_name %>
  <%= submit_tag 'Create' %>
<% end %>

شيفرة HTML التي أُنشِئَت لهذا ستكون:

<form class="new_person" id="new_person" action="/people" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input type="hidden" name="authenticity_token" value="lTuvBzs7ANygT0NFinXj98tfw3Emfm65wwYLbUvoWsK2pngccIQSUorM2C035M9dZswXgWTvKwFS8W5TVblpYw==" />
  <input type="text" name="person[first_name]" id="person_first_name" />
  <input type="text" name="person[last_name]" id="person_last_name" />
  <input type="submit" name="commit" value="Create" data-disable-with="Create" />
</form>

سبيدو الكائن params الذي أُنشِئَ عند إرسال هذا النموذج بالشكل:

{"utf8" => "✓", "authenticity_token" => "lTuvBzs7ANygT0NFinXj98tfw3Emfm65wwYLbUvoWsK2pngccIQSUorM2C035M9dZswXgWTvKwFS8W5TVblpYw==", "person" => {"first_name" => "William", "last_name" => "Smith"}, "commit" => "Create", "controller" => "people", "action" => "create"}

يحتوي الكائن params ذي النوع Hash على قيمة شخص (person) متداخلة، وبالتالي يمكن الوصول إليها باستخدام params[:person]‎ في وحدة التحكم.

check_box

يعيد وسم مربع اختيار مصمم للوصول إلى خاصية محددة.

# هي 1 @article.validated? لنَقُل أن
check_box("article", "validated")
# => <input type="checkbox" id="article_validated" name="article[validated]" value="1" />
#    <input name="article[validated]" type="hidden" value="0" />

fields_for

ينشئ نطاقًا حول كائن نموذج محدد مثل form_for، ولكن لا ينشئ وسوم النموذج نفسها. وهذا يجعل fields_for  مناسبة لتحديد كائنات نماذج إضافية في نفس النموذج:

<%= form_for @person, url: { action: "update" } do |person_form| %>
  First name: <%= person_form.text_field :first_name %>
  Last name : <%= person_form.text_field :last_name %>
 
  <%= fields_for @person.permission do |permission_fields| %>
    Admin?  : <%= permission_fields.check_box :admin %>
  <% end %>
<% end %>

file_field

يعيد وسم إدخال لتحميل ملف مصمم خصيصًا للوصول إلى خاصية محددة.

file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />

form_for

يُنشِئ نموذجًا ونطاقًا حول كائن نموذج (model object) محدد يُستخدم كأساس للاستعلام عن قيم الحقول.

<%= form_for @article do |f| %>
  <%= f.label :title, 'Title' %>:
  <%= f.text_field :title %><br>
  <%= f.label :body, 'Body' %>:
  <%= f.text_area :body %><br>
<% end %>

hidden_field

يعيد وسم إدخال مخفي مصمم للوصول إلى خاصية محددة.

hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />

label

يعيد وسم تسمية مصمم لتسمية حقل إدخال لخاصية محددة.

label(:article, :title)
# => <label for="article_title">Title</label>

password_field

يعيد وسم إدخال من نوع "كلمة المرور" مصمم للوصول إلى خاصية محددة.

password_field(:login, :pass)
# => <input type="text" id="login_pass" name="login[pass]" value="#{@login.pass}" />

radio_button

يعيد وسم زر من النوع radio للدخول إلى خاصية محددة.

# "rails" يعيد @article.category لنفترض أن
radio_button("article", "category", "rails")
radio_button("article", "category", "java")
# => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
#    <input type="radio" id="article_category_java" name="article[category]" value="java" />

text_area

يعيد مجموعة وسوم فتح وإغلاق لحقل نصي متعدد الأسطر <textarea> مصممة خصيصًا للوصول لخاصية محددة.

text_area(:comment, :text, size: "20x30")
# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
#      #{@comment.text}
#    </textarea>

text_field

يعيد وسم  إدخال من النوع "نص" (text) مخصص للوصول لخاصية محددة.

text_field(:article, :title)
# => <input type="text" id="article_title" name="article[title]" value="#{@article.title}" />

email_field

يعيد وسم  إدخال من النوع "بريد الإلكتروني" (email) مخصص للوصول لخاصية  محددة.

email_field(:user, :email)
# => <input type="email" id="user_email" name="user[email]" value="#{@user.email}" />

url_field

يعيد وسم  إدخال من النوع "url" مخصص للوصول لخاصية محددة.

url_field(:user, :url)
# => <input type="url" id="user_url" name="user[url]" value="#{@user.url}" />

المساعد FormOptionsHelper

يوفر عددًا من الدوال لتحويل أنواع مختلفة من الحاويات إلى مجموعة من وسم الاختيار.

collection_select

يعيد الوسمين <select> و <option> لتجميع قيم الإعادة الحالية للتابع method من أجل صنف الكائن (object's class).

مثال بنية الكائن للاستخدام مع هذا التابع:

class Article < ApplicationRecord
  belongs_to :author
end
 
class Author < ApplicationRecord
  has_many :articles
  def name_with_initial
    "#{first_name.first}. #{last_name}"
  end
end

استخدام بسيط (تحديد المؤلف المرتبط لنسخة المقالة article@):

collection_select(:article, :author_id, Author.all, :id, :name_with_initial, { prompt: true })

إذا كانت قيمة article.author_id@ هي 1، فسيعيد هذا:

<select name="article[author_id]">
  <option value="">Please select</option>
  <option value="1" selected="selected">D. Heinemeier Hansson</option>
  <option value="2">D. Thomas</option>
  <option value="3">M. Clark</option>

collection_radio_buttons

يعيد وسوم radio_button لتجميع قيم الإعادة الحالية للتابع method من أجل صنف الكائن (object's class).

مثال بنية الكائن للاستخدام مع هذا التابع:

class Article < ApplicationRecord
  belongs_to :author
end
 
class Author < ApplicationRecord
  has_many :articles
  def name_with_initial
    "#{first_name.first}. #{last_name}"
  end
end

استخدام بسيط (تحديد المؤلف المرتبط لنسخة مقال، article@):

collection_radio_buttons(:article, :author_id, Author.all, :id, :name_with_initial)

إذا كانت قيمة article.author_id@ هي 1، فسيعيد هذا:

<input id="article_author_id_1" name="article[author_id]" type="radio" value="1" checked="checked" />
<label for="article_author_id_1">D. Heinemeier Hansson</label>
<input id="article_author_id_2" name="article[author_id]" type="radio" value="2" />
<label for="article_author_id_2">D. Thomas</label>
<input id="article_author_id_3" name="article[author_id]" type="radio" value="3" />
<label for="article_author_id_3">M. Clark</label>

collection_check_boxes

يعيد وسوم check_box لتجميع قيم الإعادة الحالية للتابع method من أجل صنف الكائن (object's class).

مثال بنية الكائن للاستخدام مع هذا التابع:

class Article < ApplicationRecord
  has_and_belongs_to_many :authors
end
 
class Author < ApplicationRecord
  has_and_belongs_to_many :articles
  def name_with_initial
    "#{first_name.first}. #{last_name}"
  end
end

استخدام بسيط (تحديد المؤلفين المرتبطين بنسخة مقال، أي article@):

collection_check_boxes(:article, :author_ids, Author.all, :id, :name_with_initial)

إذا كانت قيمة article.author_id@ هي 1، فسيعيد هذا:

<input id="article_author_ids_1" name="article[author_ids][]" type="checkbox" value="1" checked="checked" />
<label for="article_author_ids_1">D. Heinemeier Hansson</label>
<input id="article_author_ids_2" name="article[author_ids][]" type="checkbox" value="2" />
<label for="article_author_ids_2">D. Thomas</label>
<input id="article_author_ids_3" name="article[author_ids][]" type="checkbox" value="3" />
<label for="article_author_ids_3">M. Clark</label>
<input name="article[author_ids][]" type="hidden" value="" />

option_groups_from_collection_for_select

يعيد سلسلة وسوم <option> مثل options_from_collection_for_select، لكن يجمِّعهم في وسوم <optgroup> استنادًا إلى علاقات الكائنات الخاصة بالوسائط.

مثال بنية الكائن للاستخدام مع هذا التابع:

class Continent < ApplicationRecord
  has_many :countries
  # attribs: id, name
end
 
class Country < ApplicationRecord
  belongs_to :continent
  # attribs: id, name, continent_id
end

استخدام بسيط:

option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)

الناتج المحتمل:

<optgroup label="Africa">
  <option value="1">Egypt</option>
  <option value="4">Rwanda</option>
  ...
</optgroup>
<optgroup label="Asia">
  <option value="3" selected="selected">China</option>
  <option value="12">India</option>
  <option value="5">Japan</option>
  ...
</optgroup>

ملاحظة: يعاد فقط وسوم <optgroup> و <option>، لذلك لا يزال يتعين عليك تجميع الناتج في وسم <select> مناسب.

options_for_select

يقبل حاوية (جدول Hash، مصفوفة، كائن من النوع enumerable، نوعك) ويعيد سلسلة من وسوم <option>.

options_for_select([ "VISA", "MasterCard" ])
# => <option>VISA</option> <option>MasterCard</option>

ملاحظة: تُعَاد وسوم <option> فقط، لذا يجب عليك تجميع هذا الاستدعاء في وسم <select> العادي.

options_from_collection_for_select

يعيد سلسلة وسوم <option> فسِّرت بواسطة التكرار عبر المجموعة collection وعينت نتيجة استدعاء value_method كقيمة الخيار و text_method كنص الخيار.

# options_from_collection_for_select(collection, value_method, text_method, selected = nil)

على سبيل المثال، تخيل حلقة تتكرر على كل شخص في ‎@project.people لتوليد وسم إدخال:

options_from_collection_for_select(@project.people, "id", "name")
# => <option value="#{person.id}">#{person.name}</option>

ملاحظة: تُعَاد وسوم <option> فقط، لذا يجب عليك تجميع هذا الاستدعاء في وسم <select> العادي.

select

يُنشئ وسم <select> وسلسلة من وسوم <option> للكائن والتابع المعطيين. إليك المثال التالي:

select("article", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })

إذا كانت قيمة article.author_id@ هي 1، فسيصبح هذا:

<select name="article[person_id]">
  <option value=""></option>
  <option value="1" selected="selected">David</option>
  <option value="2">Eileen</option>
  <option value="3">Rafael</option>
</select>

time_zone_options_for_select

يعيد سلسلة وسوم اختيار نصية إلى حد كبير في أي منطقة زمنية في العالم.

time_zone_select

يعيد وسوم تحديد <select> واختيار <option> للكائن والدالة المعينَين، باستخدام time_zone_options_for_select لإنشاء قائمة من وسوم <option>.

time_zone_select("user", "time_zone")

date_field

يعيد وسم إدخال <input> من النوع "تاريخ" مصمم للوصول إلى خاصية محددة.

date_field("user", "dob")

المساعد FormTagHelper

يوفر عددًا من التوابع لإنشاء وسوم النموذج التي لا تعتمد على كائن Active Record المعين إلى القالب مثل FormHelper. بدلًا من ذلك، يمكنك تقديم الأسماء والقيم يدويًا.

check_box_tag

ينشئ وسوم إدخال نموذج من نوع مربع اختيار.

check_box_tag 'accept'
# => <input id="accept" name="accept" type="checkbox" value="1" />

field_set_tag

ينشئ مجموعة حقول لتجميع عناصر نموذج HTML.

<%= field_set_tag do %>
  <p><%= text_field_tag 'name' %></p>
<% end %>
# => <fieldset><p><input id="name" name="name" type="text" /></p></fieldset>

file_field_tag

يُنشئ حقل تحميل الملفات.

<%= form_tag({ action: "post" }, multipart: true) do %>
  <label for="file">File to Upload</label> <%= file_field_tag "file" %>
  <%= submit_tag %>
<% end %>

مثال على الناتج:

file_field_tag 'attachment'
# => <input id="attachment" name="attachment" type="file" />

form_tag

يبدأ وسم نموذج بتوجيه الإجراء إلى عنوان URL هُيِّئ باستخدام url_for_options تمامًا مثل ActionController::Base.url_for.

<%= form_tag '/articles' do %>
  <div><%= submit_tag 'Save' %></div>
<% end %>
# => <form action="/articles" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>

hidden_field_tag

ينشئ حقل إدخال نموذج مخفي يستخدم لنقل البيانات التي قد تفقد بسبب انعدام الثبات في HTTP أو البيانات التي يجب أن تكون مخفية عن المستخدم.

hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
# => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />

image_submit_tag

يعرض صورة تعمل عند النقر عليها على إرسال النموذج.

image_submit_tag("login.png")
# => <input src="/images/login.png" type="image" />

label_tag

ينشئ حقل تسمية.

label_tag 'name'
# => <label for="name">Name</label>

password_field_tag

ينشئ حقل كلمة مرور، وهو حقلٌ نصيٌّ مقنَّع يخفي إدخالات المستخدمين خلف قناع.

password_field_tag 'pass'
# => <input id="pass" name="pass" type="password" />

radio_button_tag

ينشئ زرًا من النوع radio؛ استخدم مجموعات من أزرار هذا النوع للسماح للمستخدمين باختيار خيار وحيد من بين مجموعة من الخيارات.

radio_button_tag 'gender', 'male'
# => <input id="gender_male" name="gender" type="radio" value="male" />

select_tag

ينشئ مربع اختيار لقائمة منسدلة.

select_tag "people", "<option>David</option>"
# => <select id="people" name="people"><option>David</option></select>

submit_tag

ينشئ زر إرسال مع استعمال النص المعطى كتسمية توضيحية.

submit_tag "Publish this article"
# => <input name="commit" type="submit" value="Publish this article" />

text_area_tag

ينشئ منطقة إدخال نصية؛ يستعمل الوسم <textarea> لإدخالات نصية متعددة الأسطر مثل مشاركات المدونات أو الشروحات.

text_area_tag 'article'
# => <textarea id="article" name="article"></textarea>

text_field_tag

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

text_field_tag 'name'
# => <input id="name" name="name" type="text" />

email_field_tag

ينشئ حقل إدخال قياسي لإدخال عناوين البريد الإلكتروني.

email_field_tag 'email'
# => <input id="email" name="email" type="email" />

url_field_tag

ينشئ حقل إدخال قياسي لإدخال عنوان url.

url_field_tag 'url'
# => <input id="url" name="url" type="url" />

date_field_tag

ينشئ حقل إدخال قياسي لإدخال التاريخ.

date_field_tag "dob"
# => <input id="dob" name="dob" type="date" />

المساعد JavaScriptHelper

يوفر العمل مع جافاسكربت في عروضك.

escape_javascript

يهرِّب محرف العودة (carrier returns) وعلامة الاقتباس الفردية والمزدوجة لأجزاء شيفرات جافاسكربت.

javascript_tag

يعيد وسم جافاسكربت يحوي بداخله الشيفرة المعطاة.

javascript_tag "alert('All is good')"
<script>
//<![CDATA[
alert('All is good')
//]]>
</script>

المساعد NumberHelper

يوفر توابعًا لتحويل الأرقام إلى سلاسل نصية منسقة. تُوفَّر توفر هذه التوابع من أجل أرقام هاتف، والعملة، والنسبة المئوية، والدقة، والتدوين الموضعي (positional notation)، وحجم ملف.

number_to_currency

ينسق عددًا في صيغة عملة ثم يضعه في سلسلة نصية (مثل 13.65$).

number_to_currency(1234567890.50) # => $1,234,567,890.50

number_to_human_size

ينسق حجم البايتات المعطاة إلى قيمة أكثر قابلية للفهم. هذا مفيد في الإبلاغ عن أحجام الملفات للمستخدمين.

number_to_human_size(1234)          # => 1.2 KB
number_to_human_size(1234567)       # => 1.2 MB

number_to_percentage

ينسق عددًا في صيغة نسبة مئوية ويحوله إلى سلسلة نصية.

number_to_percentage(100, precision: 0)        # => 100%

number_to_phone

ينسق عددًا بصيغة رقم هاتف (بنمط الولايات المتحدة بشكل افتراضي).

number_to_phone(1235551234) # => 123-555-1234

number_with_delimiter

ينسق عددًا بتجميع منازل الآلاف فيه عبر فصلها عن بعضها بفاصل (فاصلة الآلاف).

number_with_delimiter(12345678) # => 12,345,678

number_with_precision

ينسق عددًا بمستوى الدقة المحدد، والذي يُعَيَّن افتراضيًا إلى 3 (عدد المنازل بعد الفاصلة).

number_with_precision(111.2345)     # => 111.235
number_with_precision(111.2345, precision: 2)  # => 111.23

المساعد SanitizeHelper

توفر الوحدة SanitizeHelper مجموعة من التوابع لإزالة عناصر HTML غير مرغوب فيها.

sanitize

يرمِّز المساعد sanitize هذا كل الوسوم ويزيل كل الخاصيات غير المسموح بها بشكل محدد.

sanitize @article.body

إذا مُرر أحد الخيارين attributes: أو tags:، فلا يُسمح إلا بالخاصيات والوسوم المذكورة معه فقط وسيزال كل شيء آخر.

sanitize @article.body, tags: %w(table tr td), attributes: %w(id class style)

لتغيير الإعدادات الافتراضية لاستخدامات متعددة مثل إضافة وسوم الجدول إلى الإعدادات الافتراضية:

class Application < Rails::Application
  config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
end

sanitize_css(style)‎

ينظف كتلة من شيفرة CSS.

(strip_links(html‎

يزيل وسوم الربط من النص المُمرَّر إليه ويترك المحتوى النصي فقط.

strip_links('<a href="http://rubyonrails.org">Ruby on ريلز</a>')

strip_links('<a href="http://rubyonrails.org">Ruby on Rails</a>')
# => Ruby on Rails
strip_links('emails to <a href="mailto:me@email.com">me@email.com</a>.')
# => emails to me@email.com.
strip_links('Blog: <a href="http://myblog.com/">Visit</a>.')
# => Blog: Visit.

strip_tags(html)‎

يزيل كل وسوم HTML من شيفرة html المُمررة إليه من ضمنها التعليقات. آلية عمل هذا التابع مدعومة بواسطة الجوهرة rails-html-sanitizer.

strip_tags("Strip <i>these</i> tags!")
# => Strip these tags
strip_tags("<b>Bold</b> no more!  <a href='more.html'>See more</a>")
# => Bold no more!  See more

ملاحظة: قد لا يزال الناتج يحتوي على المحارف "<" و ">" و "&" غير المهربة ويربك المتصفحات.

المساعد CsrfHelper

يعيد وسوم البيانات الوصفية "csrf-param" و"csrf-token" مع اسم معامل (parameter) ورمز (token) حماية طلب التزوير عبر الموقع على التوالي.

<%= csrf_meta_tags %>

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

عروض متعلقة بالمحليَّة

يحوي Action View على قابلية عرض قوالب مختلفة استنادًا إلى الإعدادات المحلية (locale) الحالية.

على سبيل المثال، افترض أن لديك المتحكم MaterialController مع Action View. بشكل افتراضي، استدعاء Action View هذا سيصيِّر العرض app/views/articles/show.html.erb. ولكن إذا ضبطت المحلية بالشكل I18n.locale = :de، فسيصيِّر العرض app/views/articles/show.de.html.erb بدلًا من ذلك. إذا كان القالب الخاص بالمحلية (المحلية de هنا) غير موجود، فستُستخدًم النسخة غير المزخرفة. هذا يعني أنك لست مطالبًا بتقديم عروض متعلقة بالمحلية لجميع الحالات، ولكن ستُفضَّل وتُستخدَم إذا كانت متوافرة.

يمكنك استخدام نفس التقنية لتخصيص ملفات الإنقاذ (rescue files) في المجلد العام بناءً على قيمة المحلية. على سبيل المثال، ضبط I18n.locale = :de وإنشاء public/500.de.html و public/404.de.html يسمح لك بعرض صفحات الإنقاذ بما يتوافق مع قيمة المحلية المضبوطة، التي هي de في حالتنا هذه.

نظرًا لأن ريلز لا يقيد الرموز المستخدمة لتعيين المحلية I18n.locale، يمكنك الاستفادة من هذا الأمر لعرض محتوى مختلف اعتمادًا على أي شيء يعجبك. على سبيل المثال، لنفترض أن لديك بعض المستخدمين "الخبراء" الذين يمكنهم مشاهدة صفحات مختلفة من المستخدمين "العاديين". يمكنك إضافة ما يلي إلى الملف app/controllers/application.rb:

before_action :set_expert_locale
 
def set_expert_locale
  I18n.locale = :expert if current_user.expert?
end

بعد ذلك، يمكنك إنشاء عروض خاصة مثل app/views/articles/show.expert.html.erb والتي تُعرَض فقط للمستخدمين الخبراء.

يمكنك قراءة المزيد عن تدويل في دليل الواجهة البرمجة لتدويل تطبيقات ريلز.

مصادر