الفرق بين المراجعتين لصفحة: «Rails/routing»
جميل-بيلوني (نقاش | مساهمات) إنشاء الصفحة؛ هذه الصفحة من مساهمات دعاء فرح |
جميل-بيلوني (نقاش | مساهمات) طلا ملخص تعديل |
||
(2 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
يغطي هذا الدليل الميزات التي يواجهها المستخدم في عمليات التوجيه في | <noinclude>{{DISPLAYTITLE:التوجيه من الخارج إلى الداخل في ريلز}}</noinclude> | ||
[[تصنيف:Rails]] | |||
[[تصنيف:Rails Controllers]] | |||
يغطي هذا الدليل الميزات التي يواجهها المستخدم في عمليات التوجيه في ريلز. | |||
بعد قراءة هذا الدليل، ستعرف: | بعد قراءة هذا الدليل، ستعرف: | ||
* كيفية تفسير الشيفرة في config/routes.rb. | * كيفية تفسير الشيفرة في config/routes.rb. | ||
* كيفية بناء المسارات الخاصة بك باستخدام إما أسلوب الحيلة (resourceful style) المفضل أو طريقة المطابقة (match method). | * كيفية بناء المسارات الخاصة بك باستخدام إما أسلوب الحيلة (resourceful style) المفضل أو طريقة المطابقة (match method). | ||
* كيفية الإعلان عن معاملات المسار الموجه، والتي تمرر إلى إجراءات وحدة التحكم (controller actions). | * كيفية الإعلان عن معاملات المسار الموجه، والتي تمرر إلى إجراءات [[Rails/action controller overview|وحدة التحكم]] (controller actions). | ||
* كيفية إنشاء المسارات وعناوين URL تلقائيًا باستخدام مساعدي المسار الموجه. | * كيفية إنشاء المسارات وعناوين URL تلقائيًا باستخدام مساعدي المسار الموجه. | ||
* التقنيات المتقدمة مثل إنشاء قيود وتثبيت نقاط نهاية Rack. | * التقنيات المتقدمة مثل إنشاء قيود وتثبيت نقاط نهاية Rack. | ||
== الغرض من توجيه المسارات في | == الغرض من توجيه المسارات في ريلز == | ||
يتعرف جهاز التوجيه في | يتعرف جهاز التوجيه في ريلز على عناوين URL ويرسلها إلى إجراء وحدة التحكم [[Rails/action controller overview|Action Controller]]، أو إلى تطبيق Rack. ويمكنه أيضًا إنشاء مسارات وعناوين URL، مع تجنب الحاجة إلى استخدام رموز ثابتة في الواجهة الخاصة بك. | ||
=== توصيل عناوين URL بالشيفرة === | === توصيل عناوين URL بالشيفرة === | ||
عندما يتلقى تطبيق | عندما يتلقى تطبيق ريلز طلبًا واردًا مثل: <code>GET /patients/17</code> يطلب من جهاز التوجيه مطابقته مع إجراء وحدة تحكم [[Rails/action controller overview|Action Controller]]. إذا كان أول مسار مطابق هو:<syntaxhighlight lang="rails"> | ||
يطلب من جهاز التوجيه مطابقته مع إجراء وحدة تحكم. إذا كان أول مسار مطابق هو:<syntaxhighlight lang="rails"> | |||
get '/patients/:id', to: 'patients#show' | get '/patients/:id', to: 'patients#show' | ||
</syntaxhighlight> | </syntaxhighlight>يرسل الطلب إلى وحدة التحكم <code>patients</code> الخاص بالإجراء <code>show</code> مع <code>{ id: '17' }</code> في <code>params</code>. | ||
يرسل الطلب إلى وحدة التحكم patients | |||
=== إنشاء مسارات وعناوين URL من الشيفرة === | === إنشاء مسارات وعناوين URL من الشيفرة === | ||
يمكنك أيضًا إنشاء مسارات وعناوين URL. إذا تم تعديل المسار الموجه أعلاه ليكون: | يمكنك أيضًا إنشاء مسارات وعناوين URL. إذا تم تعديل المسار الموجه أعلاه ليكون:<syntaxhighlight lang="rails"> | ||
get '/patients/:id', to: 'patients#show', as: 'patient' | get '/patients/:id', to: 'patients#show', as: 'patient' | ||
</syntaxhighlight>ويحتوي التطبيق الخاص بك على هذا الرمز في وحدة التحكم:<syntaxhighlight lang="rails"> | |||
ويحتوي التطبيق الخاص بك على هذا الرمز في وحدة التحكم: | |||
@patient = Patient.find(params[:id]) | @patient = Patient.find(params[:id]) | ||
</syntaxhighlight>وهذا في الواجهة يقابل:<syntaxhighlight lang="rails"> | |||
وهذا في الواجهة يقابل: | |||
<%= link_to 'Patient Record', patient_path(@patient) %> | <%= link_to 'Patient Record', patient_path(@patient) %> | ||
</syntaxhighlight>ثم ينشئ جهاز التوجيه المسار /patients/17. هذا يقلل من هشاشة الواجهة الخاص بك ويجعل التعليمات البرمجية الخاصة بك أسهل للفهم. لاحظ أن الهوية <code>id</code> لا تحتاج إلى التحديد في مساعد المسار الموجه. | |||
=== تهيئة جهاز توجيه المسارات في ريلز === | |||
توجد المسارات الموجهة للتطبيق أو المحرك (engine) في الملف config/routes.rb وعادةً ما تبدو كالتالي:<syntaxhighlight lang="rails"> | |||
=== تهيئة جهاز توجيه المسارات في | |||
توجد المسارات الموجهة للتطبيق أو المحرك (engine) في الملف config/routes.rb وعادةً ما تبدو كالتالي: | |||
Rails.application.routes.draw do | Rails.application.routes.draw do | ||
resources :brands, only: [:index, :show] do | |||
resources :products, only: [:index, :show] | |||
end | |||
resource :basket, only: [:show, :update, :destroy] | |||
resolve("Basket") { route_for(:basket) } | |||
end | |||
</syntaxhighlight>نظرًا لأن هذا ملف مصدر روبي منتظم، يمكنك استخدام جميع ميزاته لمساعدتك في تحديد مساراتك الموجهة، لكن كن حذرًا مع أسماء المتغيرات، إذ إنها يمكن أن تتعارض مع توابع DSL الخاصة بالموجه. | |||
< | '''ملاحظة''': تقوم الكتلة <code>Rails.application.routes.draw do… end</code> التي تلتزم بتعريفات المسار الموجه الخاصة بك بإنشاء النطاق الخاص بجهاز التوجيه DSL ويجب عدم حذفه. | ||
== توجيه المورد: الافتراضي في ريلز == | |||
يتيح لك توجيه الموارد إمكانية الإعلان بسرعة عن جميع المسارات الشائعة لوحدة التحكم كثيرة الموارد. بدلًا من الإعلان عن مسارات موجهة منفصلة للإجراءات <code>index</code>، و <code>show</code>، و <code>new</code>، و <code>edit</code>، و <code>create</code>، و <code>update</code> و <code>destroy</code> الخاصة بك، فإن المسار كثير المورد يعلن عنه في سطر واحد من الشيفرة. | |||
== توجيه المورد: الافتراضي في | |||
يتيح لك توجيه الموارد إمكانية الإعلان بسرعة عن جميع المسارات الشائعة لوحدة التحكم كثيرة الموارد. بدلًا من الإعلان عن مسارات موجهة منفصلة للإجراءات | |||
=== الموارد على الويب === | === الموارد على الويب === | ||
تطلب صفحات المتصفحات من | تطلب صفحات المتصفحات من ريلز عن طريق تقديم طلب لعنوان URL باستخدام تابع HTTP محدد، مثل GET و POST و PATCH و PUT و DELETE. كل تابع هو طلب لتنفيذ عملية على المورد. يحدد مسار المورد الموجه عددًا من الطلبات ذات الصلة بالإجراءات في وحدة التحكم الواحدة. | ||
عندما يتلقى تطبيق ريلز طلبًا واردًا لما يلي:<syntaxhighlight lang="http"> | |||
DELETE /photos/17 | DELETE /photos/17 | ||
</syntaxhighlight>يطلب من جهاز التوجيه لتعيينه إلى إجراء وحدة تحكم [[Rails/action controller overview|Action Controller]]. إذا كان أول مسار مطابق هو:<syntaxhighlight lang="rails"> | |||
يطلب من جهاز التوجيه لتعيينه إلى إجراء وحدة تحكم. إذا كان أول مسار مطابق هو: | resources :photos | ||
</syntaxhighlight>سترسل ريلز ذلك الطلب للإجراء <code>destroy</code> على وحدة التحكم <code>photos</code> مع <code>{id: '17'}</code> في <code>params</code>. | |||
سترسل | |||
=== CRUD والأفعال والإجراءات === | === CRUD والأفعال والإجراءات === | ||
في | في ريلز، يوفر المسار كثير المورد تخطيطًا بين أفعال HTTP وعناوين URL لإجراءات التحكم. من خلال الاتفاقية، كل إجراء يخطط أيضًا لعملية CRUD محددة في قاعدة البيانات. إدخال فردي في ملف التوجيه يكون مثل:<syntaxhighlight lang="rails"> | ||
resources :photos | |||
</syntaxhighlight>ينشئ سبعة مسارات مختلفة في التطبيق الخاص بك معيَّنةً جميعها إلى وحدة التحكم <code>Photos</code>: | |||
ينشئ سبعة مسارات مختلفة في التطبيق الخاص بك معيَّنةً جميعها إلى وحدة | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!الاستخدامات | |||
|- | |- | ||
|GET | |GET | ||
|/photos | |/photos | ||
|photos#index | |<code>photos#index</code> | ||
|عرض قائمة بجميع الصور. | |عرض قائمة بجميع الصور. | ||
|- | |- | ||
|GET | |GET | ||
|/photos/new | |/photos/new | ||
|photos#new | |<code>photos#new</code> | ||
|إرجاع نموذج HTML لإنشاء صورة جديدة. | |إرجاع نموذج HTML لإنشاء صورة جديدة. | ||
|- | |- | ||
|POST | |POST | ||
|/photos | |/photos | ||
|photos#create | |<code>photos#create</code> | ||
|خلق صورة جديدة. | |خلق صورة جديدة. | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id | |/photos/:id | ||
|photos#show | |<code>photos#show</code> | ||
|عرض صورة محددة. | |عرض صورة محددة. | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id/edit | |/photos/:id/edit | ||
|photos#edit | |<code>photos#edit</code> | ||
|إرجاع نموذج HTML لتحرير صورة. | |إرجاع نموذج HTML لتحرير صورة. | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/photos/:id | |/photos/:id | ||
|photos#update | |<code>photos#update</code> | ||
|تحديث صورة معينة. | |تحديث صورة معينة. | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/photos/:id | |/photos/:id | ||
|photos#destroy | |<code>photos#destroy</code> | ||
|حذف صورة معينة. | |حذف صورة معينة. | ||
|} | |} | ||
ملاحظة: نظرًا لأن جهاز التوجيه يستخدم الفعل HTTP وعنوان URL لمطابقة الطلبات الواردة، فإن أربعة عناوين URL تتحول إلى سبعة إجراءات مختلفة. | '''ملاحظة''': نظرًا لأن جهاز التوجيه يستخدم الفعل HTTP وعنوان URL لمطابقة الطلبات الواردة، فإن أربعة عناوين URL تتحول إلى سبعة إجراءات مختلفة. | ||
ملاحظة: تُطابَق مسارات | '''ملاحظة''': تُطابَق مسارات ريلز بالترتيب المحدد لها، لذلك إذا كانت لديك <code>resources :photos</code> الموجودة أعلى <code>get photos/poll</code>، فسيطابق مسار الإجراء <code>show</code> السطر <code>resources</code> قبل سطر <code>get</code>. لحل هذه المشكلة، قم بتحريك سطر <code>get</code> فوق سطر <code>resources</code> بحيث يطابقه أولًا. | ||
=== المسار ومساعد URL === | === المسار ومساعد URL === | ||
سيؤدي إنشاء مسار موجه كثير المورد إلى كشف عدد من المساعدين إلى وحدات التحكم في تطبيقك. في حالة resources :photos: | سيؤدي إنشاء مسار موجه كثير المورد إلى كشف عدد من المساعدين إلى وحدات التحكم في تطبيقك. في حالة <code>resources :photos</code>: | ||
* photos_path returns /photos | * <code>photos_path returns /photos</code> | ||
* new_photo_path returns /photos/new | * <code>new_photo_path returns /photos/new</code> | ||
* edit_photo_path(:id) returns /photos/:id/edit (for instance, edit_photo_path(10) returns /photos/10/edit) | * <code>edit_photo_path(:id) returns /photos/:id/edit (for instance, edit_photo_path(10) returns /photos/10/edit)</code> | ||
* photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10) | * <code>photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10)</code> | ||
كل من هؤلاء المساعدين لديه مساعد | كل من هؤلاء المساعدين لديه مساعد <code>_url</code> مقابل (مثل <code>photos_url</code>) الذي يعيد نفس المسار مسبوقًا ببادئة المضيف والمنفذ والمسار الحالي. | ||
=== تحديد موارد متعددة في نفس الوقت === | === تحديد موارد متعددة في نفس الوقت === | ||
إذا كنت بحاجة إلى إنشاء مسارات توجيه لأكثر من مورد واحد، فيمكنك توفير جزء من الكتابة عن طريق تعريفهم جميعًا باستدعاءٍ واحدٍ إلى resources: | إذا كنت بحاجة إلى إنشاء مسارات توجيه لأكثر من مورد واحد، فيمكنك توفير جزء من الكتابة عن طريق تعريفهم جميعًا باستدعاءٍ واحدٍ إلى <code>resources</code>:<syntaxhighlight lang="rails"> | ||
resources :photos, :books, :videos | |||
</syntaxhighlight>هذا يعمل بالضبط بطريقة مشابهة للشيفرة التالية:<syntaxhighlight lang="rails"> | |||
هذا يعمل بالضبط بطريقة مشابهة للشيفرة التالية: | |||
resources :photos | resources :photos | ||
resources :books | resources :books | ||
resources :videos | resources :videos | ||
</syntaxhighlight> | |||
=== الموارد الفردية === | === الموارد الفردية === | ||
في بعض الأحيان، يكون لديك مورد يبحث عنه العملاء دائمًا دون الإشارة إلى معرف ID. على سبيل المثال، ترغب في أن يعرض /profile دائمًا ملف تعريف المستخدم الذي قام بتسجيل الدخول حاليًا. في هذه الحالة، يمكنك استخدام مورد مفرد لتعيين /profile (بدلًا من /profile/:id) إلى الإجراء show: | في بعض الأحيان، يكون لديك مورد يبحث عنه العملاء دائمًا دون الإشارة إلى معرف ID. على سبيل المثال، ترغب في أن يعرض /profile دائمًا ملف تعريف المستخدم الذي قام بتسجيل الدخول حاليًا. في هذه الحالة، يمكنك استخدام مورد مفرد لتعيين /profile (بدلًا من /profile/:id) إلى الإجراء <code>show</code>:<syntaxhighlight lang="rails"> | ||
get 'profile', to: 'users#show' | get 'profile', to: 'users#show' | ||
</syntaxhighlight>تمرير سلسلة نصية (String) إلى <code>to:</code> ستتوقع أن تكون بالتنسيق <code>controller#action</code>. عند استخدام [[Ruby/Symbol|رمز]] (Symbol)، يجب استبدال الخيار <code>to:</code> بالقيمة <code>action:</code>. عند استخدام سلسلة نصية دون الرمز <code>#</code>، يجب استبدال الخيار <code>to:</code> بـ <code>controller:</code> بالشكل التالي:<syntaxhighlight lang="rails"> | |||
تمرير سلسلة نصية (String) إلى to: ستتوقع أن تكون بالتنسيق controller#action. عند استخدام رمز (Symbol)، يجب استبدال الخيار to: بالقيمة action:. عند استخدام سلسلة نصية دون الرمز #، يجب استبدال الخيار to: بـ controller: بالشكل التالي: | get 'profile', action: :show, controller: 'users' | ||
</syntaxhighlight>هذا مسار موجه كثير المورد:<syntaxhighlight lang="rails"> | |||
get 'profile', action: :show, controller: 'users' | |||
هذا مسار موجه كثير المورد: | |||
resource :geocoder | resource :geocoder | ||
resolve('Geocoder') { [:geocoder] } | resolve('Geocoder') { [:geocoder] } | ||
</syntaxhighlight>يخلق ستة مسارات موجهة مختلفة في التطبيق الخاص بك كلها معيَّنة إلى وحدة التحكم <code>Geocoders</code>: | |||
يخلق ستة مسارات موجهة مختلفة في التطبيق الخاص بك كلها معيَّنة إلى وحدة | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!الإستخدامات | |||
|- | |- | ||
|GET | |GET | ||
|/geocoder/new | |/geocoder/new | ||
|geocoders#new | |<code>geocoders#new</code> | ||
|إرجاع نموذج HTML لإنشاء geocoder. | |إرجاع نموذج HTML لإنشاء geocoder. | ||
|- | |- | ||
|POST | |POST | ||
|/geocoder | |/geocoder | ||
|geocoders#create | |<code>geocoders#create</code> | ||
|إنشاء geocoder جديد. | |إنشاء geocoder جديد. | ||
|- | |- | ||
|GET | |GET | ||
|/geocoder | |/geocoder | ||
|geocoders#show | |<code>geocoders#show</code> | ||
|عرض مورد geocoder واحد و فقط. | |عرض مورد geocoder واحد و فقط. | ||
|- | |- | ||
|GET | |GET | ||
|/geocoder/edit | |/geocoder/edit | ||
|geocoders#edit | |<code>geocoders#edit</code> | ||
|إرجاع نموذج HTML لتحرير geocoder. | |إرجاع نموذج HTML لتحرير geocoder. | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/geocoder | |/geocoder | ||
|geocoders#update | |<code>geocoders#update</code> | ||
|تحديث مورد geocoder واحد و فقط. | |تحديث مورد geocoder واحد و فقط. | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/geocoder | |/geocoder | ||
|geocoders#destroy | |<code>geocoders#destroy</code> | ||
|حذف مورد geocoder. | |حذف مورد geocoder. | ||
|} | |} | ||
ملاحظة: نظرًا لأنك قد ترغب في استخدام وحدة التحكم نفسها لمسار فريد (/account) ومسار الجمع (/accounts/45)، فإن الموارد الفردية ستخضع إلى وحدات تحكم الجمع. على سبيل المثال، المورد :photo والموارد :photos تنشئ مسارات توجيه مفرد ومجتمعة تعين لنفس وحدة التحكم (PhotosController). | '''ملاحظة''': نظرًا لأنك قد ترغب في استخدام وحدة التحكم نفسها لمسار فريد (/account) ومسار الجمع (/accounts/45)، فإن الموارد الفردية ستخضع إلى وحدات تحكم الجمع. على سبيل المثال، المورد <code>:photo</code> والموارد <code>:photos</code> تنشئ مسارات توجيه مفرد ومجتمعة تعين لنفس وحدة التحكم (PhotosController). | ||
يولّد المسار الموجه كثير المورد المفرد (singular resourceful route) هؤلاء المساعدين: | يولّد المسار الموجه كثير المورد المفرد (singular resourceful route) هؤلاء المساعدين: | ||
* new_geocoder_path returns /geocoder/new | * <code>new_geocoder_path returns /geocoder/new</code> | ||
* edit_geocoder_path returns /geocoder/edit | * <code>edit_geocoder_path returns /geocoder/edit</code> | ||
* geocoder_path returns /geocoder | * <code>geocoder_path returns /geocoder</code> | ||
كما هو الحال مع موارد الجمع، فإن نفس المساعدين الذين ينتهون في _url سيتضمنون أيضًا بادئة المضيف والمنفذ والمسار. | كما هو الحال مع موارد الجمع، فإن نفس المساعدين الذين ينتهون في <code>_url</code> سيتضمنون أيضًا بادئة المضيف والمنفذ والمسار. | ||
=== وحدة تحكم مجالات الأسماء والتوجيه === | === وحدة تحكم مجالات الأسماء والتوجيه === | ||
قد ترغب في تنظيم مجموعات من وحدات التحكم تحت مجال اسم (namespace). الأكثر شيوعًا، يمكنك تجميع عدد من وحدات التحكم الإدارية تحت مجال الاسم Admin::. يمكنك وضع وحدات التحكم هذه تحت دليل app/controllers/admin، ويمكنك تجميعها معًا في جهاز التوجيه: | قد ترغب في تنظيم مجموعات من وحدات التحكم تحت مجال اسم (namespace). الأكثر شيوعًا، يمكنك تجميع عدد من وحدات التحكم الإدارية تحت مجال الاسم <code>Admin::</code>. يمكنك وضع وحدات التحكم هذه تحت دليل app/controllers/admin، ويمكنك تجميعها معًا في جهاز التوجيه:<syntaxhighlight lang="rails"> | ||
namespace :admin do | namespace :admin do | ||
resources :articles, :comments | |||
end | |||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء عدد من المسارات لكل من وحدة التحكم في <code>articles</code> و <code>comments</code>. من أجل <code>Admin::ArticlesController</code>، ستنشئ ريلز: | |||
سيؤدي ذلك إلى إنشاء عدد من المسارات لكل من وحدة التحكم في articles و comments. من أجل Admin:: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/admin/articles | |/admin/articles | ||
|admin/articles#index | |<code>admin/articles#index</code> | ||
|admin_articles_path | |<code>admin_articles_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/new | |/admin/articles/new | ||
|admin/articles#new | |<code>admin/articles#new</code> | ||
|new_admin_article_path | |<code>new_admin_article_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/admin/articles | |/admin/articles | ||
|admin/articles#create | |<code>admin/articles#create</code> | ||
|admin_articles_path | |<code>admin_articles_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|admin/articles#show | |<code>admin/articles#show</code> | ||
|admin_article_path(:id) | |<code>admin_article_path(:id)</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/:id/edit | |/admin/articles/:id/edit | ||
|admin/articles#edit | |<code>admin/articles#edit</code> | ||
|edit_admin_article_path(:id) | |<code>edit_admin_article_path(:id)</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|admin/articles#update | |<code>admin/articles#update</code> | ||
|admin_article_path(:id) | |<code>admin_article_path(:id)</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|admin/articles#destroy | |<code>admin/articles#destroy</code> | ||
|admin_article_path(:id) | |<code>admin_article_path(:id)</code> | ||
|} | |} | ||
إذا كنت تريد توجيه /articles (بدون البادئة /admin) إلى <code>Admin::ArticlesController</code>، فيمكنك استخدام:<syntaxhighlight lang="rails"> | |||
إذا كنت تريد توجيه /articles (بدون البادئة /admin) إلى Admin:: | |||
scope module: 'admin' do | scope module: 'admin' do | ||
resources :articles, :comments | |||
end | end | ||
</syntaxhighlight>أو في حالة واحدة:<syntaxhighlight lang="rails"> | |||
أو في حالة واحدة: | resources :articles, module: 'admin' | ||
</syntaxhighlight>إذا كنت تريد توجيه /admin/articles إلى <code>ArticlesController</code> (بدون بادئة الوحدة <code>Admin::</code>)، فيمكنك استخدام:<syntaxhighlight lang="rails"> | |||
إذا كنت تريد توجيه /admin/articles إلى ArticlesController (بدون بادئة الوحدة Admin::)، فيمكنك استخدام: | |||
scope '/admin' do | scope '/admin' do | ||
resources :articles, :comments | |||
end | end | ||
</syntaxhighlight>أو في حالة واحدة:<syntaxhighlight lang="rails"> | |||
أو في حالة واحدة: | resources :articles, path: '/admin/articles' | ||
</syntaxhighlight>في كل من هذه الحالات، تظل المسارات الموجهة المسماة كما هي إذا لم تستخدم النطاق (scope). في الحالة الأخيرة، تعيَّن المسارات التالية إلى <code>ArticlesController</code>: | |||
في كل من هذه الحالات، تظل المسارات الموجهة المسماة كما هي إذا لم تستخدم النطاق (scope). في الحالة الأخيرة، تعيَّن المسارات التالية إلى ArticlesController: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/admin/articles | |/admin/articles | ||
|articles#index | |<code>articles#index</code> | ||
|articles_path | |<code>articles_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/new | |/admin/articles/new | ||
|articles#new | |<code>articles#new</code> | ||
|new_article_path | |<code>new_article_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/admin/articles | |/admin/articles | ||
|articles#create | |<code>articles#create</code> | ||
|articles_path | |<code>articles_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|articles#show | |<code>articles#show</code> | ||
|article_path(:id) | |<code>article_path(:id)</code> | ||
|- | |- | ||
|GET | |GET | ||
|/admin/articles/:id/edit | |/admin/articles/:id/edit | ||
|articles#edit | |<code>articles#edit</code> | ||
|edit_article_path(:id) | |<code>edit_article_path(:id)</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|articles#update | |<code>articles#update</code> | ||
|article_path(:id) | |<code>article_path(:id)</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/admin/articles/:id | |/admin/articles/:id | ||
|articles#destroy | |<code>articles#destroy</code> | ||
|article_path(:id) | |<code>article_path(:id)</code> | ||
|} | |} | ||
ملاحظة: إذا كنت بحاجة إلى استخدام مجال اسم وحدة تحكم (controller namespace) مختلف داخل كتلة مجال الاسم (namespace block)، فيمكنك تحديد مسار جهاز تحكم مطلق، مثل: get '/foo' => '/foo#index'. | '''ملاحظة''': إذا كنت بحاجة إلى استخدام مجال اسم وحدة تحكم (controller namespace) مختلف داخل كتلة مجال الاسم (namespace block)، فيمكنك تحديد مسار جهاز تحكم مطلق، مثل: <code>get '/foo' => '/foo#index'</code>. | ||
=== الموارد المتداخلة === | === الموارد المتداخلة === | ||
من الشائع أن يكون لديك موارد منطقية للفرع childern من الموارد الأخرى. على سبيل المثال، لنفترض أن تطبيقك يتضمن هذه النماذج: | من الشائع أن يكون لديك موارد منطقية للفرع childern من الموارد الأخرى. على سبيل المثال، لنفترض أن تطبيقك يتضمن هذه النماذج:<syntaxhighlight lang="rails"> | ||
class Magazine < ApplicationRecord | class Magazine < ApplicationRecord | ||
has_many :ads | |||
end | end | ||
class Ad < ApplicationRecord | class Ad < ApplicationRecord | ||
belongs_to :magazine | |||
end | |||
</syntaxhighlight>تتيح لك المسارات المتداخلة التقاط هذه العلاقة في التوجيه الخاص بك. في هذه الحالة، يمكنك تضمين إعلان المسار هذا:<syntaxhighlight lang="rails"> | |||
تتيح لك المسارات المتداخلة التقاط هذه العلاقة في التوجيه الخاص بك. في هذه الحالة، يمكنك تضمين إعلان المسار هذا: | |||
resources :magazines do | resources :magazines do | ||
resources :ads | |||
end | end | ||
</syntaxhighlight>بالإضافة إلى المسارات الموجهة للمجلات (magazines)، سيوجه هذا الإعلان أيضًا الإعلانات إلى <code>AdsController</code>. تتطلب عناوين URL للإعلان عن مجلة: | |||
بالإضافة إلى المسارات الموجهة للمجلات (magazines)، سيوجه هذا الإعلان أيضًا الإعلانات إلى AdsController. تتطلب عناوين URL للإعلان عن مجلة: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!الاستخدامات | |||
|- | |- | ||
|GET | |GET | ||
|/magazines/:magazine_id/ads | |/magazines/:magazine_id/ads | ||
|ads#index | |<code>ads#index</code> | ||
|عرض قائمة بجميع الإعلانات لمجلة محددة. | |عرض قائمة بجميع الإعلانات لمجلة محددة. | ||
|- | |- | ||
|GET | |GET | ||
|/magazines/:magazine_id/ads/new | |/magazines/:magazine_id/ads/new | ||
|ads#new | |<code>ads#new</code> | ||
|إرجاع نموذج HTML لإنشاء إعلان جديد ينتمي إلى مجلة معينة. | |إرجاع نموذج HTML لإنشاء إعلان جديد ينتمي إلى مجلة معينة. | ||
|- | |- | ||
|POST | |POST | ||
|/magazines/:magazine_id/ads | |/magazines/:magazine_id/ads | ||
|ads#create | |<code>ads#create</code> | ||
|إنشاء إعلان جديد ينتمي إلى مجلة محددة. | |إنشاء إعلان جديد ينتمي إلى مجلة محددة. | ||
|- | |- | ||
|GET | |GET | ||
|/magazines/:magazine_id/ads/:id | |/magazines/:magazine_id/ads/:id | ||
|ads#show | |<code>ads#show</code> | ||
|عرض إعلان معين ينتمي إلى مجلة محددة. | |عرض إعلان معين ينتمي إلى مجلة محددة. | ||
|- | |- | ||
|GET | |GET | ||
|/magazines/:magazine_id/ads/:id/edit | |/magazines/:magazine_id/ads/:id/edit | ||
|ads#edit | |<code>ads#edit</code> | ||
|إرجاع نموذج HTML لتحرير إعلان ينتمي إلى مجلة معينة. | |إرجاع نموذج HTML لتحرير إعلان ينتمي إلى مجلة معينة. | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/magazines/:magazine_id/ads/:id | |/magazines/:magazine_id/ads/:id | ||
|ads#update | |<code>ads#update</code> | ||
|تحديث إعلان معين ينتمي إلى مجلة محددة. | |تحديث إعلان معين ينتمي إلى مجلة محددة. | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/magazines/:magazine_id/ads/:id | |/magazines/:magazine_id/ads/:id | ||
|ads#destroy | |<code>ads#destroy</code> | ||
|حذف إعلان معين ينتمي إلى مجلة محددة. | |حذف إعلان معين ينتمي إلى مجلة محددة. | ||
|} | |} | ||
سيؤدي هذا أيضًا إلى إنشاء مساعدين للتوجيه مثل magazine_ads_url و edit_magazine_ad_path. يأخذ هؤلاء المساعدون نسخة للمجلة كأول معامل (magazine_ads_url(@magazine)). | سيؤدي هذا أيضًا إلى إنشاء مساعدين للتوجيه مثل <code>magazine_ads_url</code> و <code>edit_magazine_ad_path</code>. يأخذ هؤلاء المساعدون نسخة للمجلة كأول معامل <code>(magazine_ads_url(@magazine))</code>. | ||
==== حدود التداخل ==== | ==== حدود التداخل ==== | ||
يمكنك أن تشعِّب الموارد ضمن الموارد المتشعبة الأخرى إذا أردت ذلك. فمثلًا: | يمكنك أن تشعِّب الموارد ضمن الموارد المتشعبة الأخرى إذا أردت ذلك. فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :publishers do | resources :publishers do | ||
resources :magazines do | |||
resources :photos | |||
end | |||
end | |||
</syntaxhighlight>تصبح الموارد المتداخلة بعمق بطيئة. في هذه الحالة مثلًا، سيتعرف التطبيق على مسارات مثل:<syntaxhighlight lang="rails"> | |||
تصبح الموارد المتداخلة بعمق بطيئة. في هذه الحالة مثلًا، سيتعرف التطبيق على مسارات مثل: | |||
/publishers/1/magazines/2/photos/3 | /publishers/1/magazines/2/photos/3 | ||
</syntaxhighlight>سيكون مساعد المسار المقابل هو <code>publisher_magazine_photo_url</code>، مما يتطلب منك تحديد كائنات على جميع المستويات الثلاثة. في الواقع، هذا الوضع مربكًا بما فيه الكفاية، إذ يقترح جيمس باك (Jamis Buck) في مقالة شائعة له قاعدةً أساسيةً لتصميم ريلز بشكل جيد: " لا ينبغي أبدًا أن تتداخل الموارد أكثر من 1 مستوى عميق." | |||
سيكون مساعد المسار المقابل هو | |||
==== التداخل الضحل ==== | ==== التداخل الضحل ==== | ||
تتمثل إحدى طرق تجنب التداخل العميق (كما هو موصى به أعلاه) في إنشاء إجراءات المجموعة المحددة ضمن الأصل | تتمثل إحدى طرق تجنب التداخل العميق (كما هو موصى به أعلاه) في إنشاء إجراءات المجموعة المحددة ضمن الأصل (parent)، وذلك للحصول على إحساس بالتسلسل الهرمي (hierarchy) ولعدم تداخل إجراءات العضو. بعبارة أخرى، لإنشاء مسارات فقط مع الحد الأدنى من المعلومات لتحديد المورد بشكل فريد، مثل هذا:<syntaxhighlight lang="rails"> | ||
resources :articles do | resources :articles do | ||
resources :comments, only: [:index, :new, :create] | |||
end | end | ||
resources :comments, only: [:show, :edit, :update, :destroy] | |||
</syntaxhighlight>تحقق هذه الفكرة توازنًا بين المسارات الوصفية والتداخل العميق. توجد صيغة مختصرة لتحقيق ذلك، عبر الخيار <code>:shallow</code>:<syntaxhighlight lang="rails"> | |||
تحقق هذه الفكرة توازنًا بين المسارات الوصفية والتداخل العميق. توجد صيغة مختصرة لتحقيق ذلك، عبر الخيار :shallow: | |||
resources :articles do | resources :articles do | ||
resources :comments, shallow: true | |||
end | end | ||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء نفس المسارات بالضبط مثل المثال الأول. يمكنك أيضًا تحديد الخيار <code>:shallow</code> في المورد الرئيسي <code>parent</code>، وفي هذه الحالة ستكون جميع الموارد المتداخلة ضحلة:<syntaxhighlight lang="rails"> | |||
سيؤدي ذلك إلى إنشاء نفس المسارات بالضبط مثل المثال الأول. يمكنك أيضًا تحديد الخيار :shallow في المورد الرئيسي | |||
resources :articles, shallow: true do | resources :articles, shallow: true do | ||
resources :comments | |||
resources :quotes | |||
resources :drafts | |||
end | end | ||
</syntaxhighlight>التابع الضحل <code>shallow</code> الذي يخص DSL يخلق مجالًا داخليًا يكون كل تداخل فيه ضحلًا. هذا ينشئ نفس المسارات الموجهة مثل المثال السابق:<syntaxhighlight lang="rails"> | |||
التابع الضحل shallow الذي يخص DSL يخلق مجالًا داخليًا يكون كل تداخل فيه ضحلًا. هذا ينشئ نفس المسارات الموجهة مثل المثال السابق: | |||
shallow do | shallow do | ||
resources :articles do | |||
resources :comments | |||
resources :quotes | |||
resources :drafts | |||
end | |||
end | end | ||
</syntaxhighlight>هناك خياران للنطاق (scope) لتخصيص المسارات الموجهة الضحلة. البادئات <code>:shallow_path</code> لمسارات العضو مع المعامل المحدد:<syntaxhighlight lang="rails"> | |||
هناك خياران للنطاق (scope) لتخصيص المسارات الموجهة الضحلة. البادئات :shallow_path لمسارات العضو مع المعامل المحدد: | |||
scope shallow_path: "sekret" do | scope shallow_path: "sekret" do | ||
resources :articles do | |||
resources :comments, shallow: true | |||
end | |||
end | end | ||
</syntaxhighlight>يحتوي مورد التعليقات هنا على المسارات التالية التي أنشئت له: | |||
يحتوي مورد التعليقات هنا على المسارات التالية التي أنشئت له: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم# الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/articles/:article_id/comments(.:format) | |/articles/:article_id/comments(.:format) | ||
|comments#index | |<code>comments#index</code> | ||
|article_comments_path | |<code>article_comments_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/articles/:article_id/comments(.:format) | |/articles/:article_id/comments(.:format) | ||
|comments#create | |<code>comments#create</code> | ||
|article_comments_path | |<code>article_comments_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/articles/:article_id/comments/new(.:format) | |/articles/:article_id/comments/new(.:format) | ||
|comments#new | |<code>comments#new</code> | ||
|new_article_comment_path | |<code>new_article_comment_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/sekret/comments/:id/edit(.:format) | |/sekret/comments/:id/edit(.:format) | ||
|comments#edit | |<code>comments#edit</code> | ||
|edit_comment_path | |<code>edit_comment_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/sekret/comments/:id(.:format) | |/sekret/comments/:id(.:format) | ||
|comments#show | |<code>comments#show</code> | ||
|comment_path | |<code>comment_path</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/sekret/comments/:id(.:format) | |/sekret/comments/:id(.:format) | ||
|comments#update | |<code>comments#update</code> | ||
|comment_path | |<code>comment_path</code> | ||
|- | |- | ||
| | |DELETE | ||
|/sekret/comments/:id(.:format) | |/sekret/comments/:id(.:format) | ||
|comments#destroy | |<code>comments#destroy</code> | ||
|comment_path | |<code>comment_path</code> | ||
|} | |} | ||
الخيار :shallow_prefix يضيف المعامل المحدد للمساعدين المسمايين: | الخيار <code>:shallow_prefix</code> يضيف المعامل المحدد للمساعدين المسمايين:<syntaxhighlight lang="rails"> | ||
scope shallow_prefix: "sekret" do | scope shallow_prefix: "sekret" do | ||
resources :articles do | |||
resources :comments, shallow: true | |||
end | |||
end | end | ||
</syntaxhighlight>يحتوي مورد التعليقات هنا على المسارات الموجهة التالية التي أنشئت له: | |||
يحتوي مورد التعليقات هنا على المسارات الموجهة التالية التي أنشئت له: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم# الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/articles/:article_id/comments(.:format) | |/articles/:article_id/comments(.:format) | ||
|comments#index | |<code>comments#index</code> | ||
|article_comments_path | |<code>article_comments_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/articles/:article_id/comments(.:format) | |/articles/:article_id/comments(.:format) | ||
|comments#create | |<code>comments#create</code> | ||
|article_comments_path | |<code>article_comments_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/articles/:article_id/comments/new(.:format) | |/articles/:article_id/comments/new(.:format) | ||
|comments#new | |<code>comments#new</code> | ||
|new_article_comment_path | |<code>new_article_comment_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/comments/:id/edit(.:format) | |/comments/:id/edit(.:format) | ||
|comments#edit | |<code>comments#edit</code> | ||
|edit_sekret_comment_path | |<code>edit_sekret_comment_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/comments/:id(.:format) | |/comments/:id(.:format) | ||
|comments#show | |<code>comments#show</code> | ||
|sekret_comment_path | |<code>sekret_comment_path</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/comments/:id(.:format) | |/comments/:id(.:format) | ||
|comments#update | |<code>comments#update</code> | ||
|sekret_comment_path | |<code>sekret_comment_path</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/comments/:id(.:format) | |/comments/:id(.:format) | ||
|comments#destroy | |<code>comments#destroy</code> | ||
|sekret_comment_path | |<code>sekret_comment_path</code> | ||
|} | |} | ||
=== اهتمامات التوجيه === | === اهتمامات التوجيه === | ||
تسمح لك اهتمامات التوجيه (Routing concerns) بالإعلان عن المسارات الموجهة الشائعة التي يمكن إعادة استخدامها داخل الموارد والمسارات الأخرى. ألق نظرة على الشيفرة التالي لمعرفة كيفية تعريف اهتمام concern: | تسمح لك اهتمامات التوجيه (Routing concerns) بالإعلان عن المسارات الموجهة الشائعة التي يمكن إعادة استخدامها داخل الموارد والمسارات الأخرى. ألق نظرة على الشيفرة التالي لمعرفة كيفية تعريف اهتمام <code>concern</code>:<syntaxhighlight lang="rails"> | ||
concern :commentable do | concern :commentable do | ||
resources :comments | |||
end | end | ||
concern :image_attachable do | concern :image_attachable do | ||
resources :images, only: :index | |||
end | end | ||
</syntaxhighlight>يمكن استخدام هذه الاهتمامات <code>concern</code> في الموارد لتجنب تكرار الرموز ومشاركة السلوك عبر المسارات:<syntaxhighlight lang="rails"> | |||
يمكن استخدام هذه الاهتمامات concern في الموارد لتجنب تكرار الرموز ومشاركة السلوك عبر المسارات: | |||
resources :messages, concerns: :commentable | resources :messages, concerns: :commentable | ||
resources :articles, concerns: [:commentable, :image_attachable] | |||
</syntaxhighlight>ما ورد أعلاه يعادل ما يلي:<syntaxhighlight lang="rails"> | |||
ما ورد أعلاه يعادل ما يلي: | |||
resources :messages do | resources :messages do | ||
resources :comments | |||
end | end | ||
resources :articles do | resources :articles do | ||
resources :comments | |||
resources :images, only: :index | |||
end | end | ||
</syntaxhighlight>كما يمكنك استخدامها في أي مكان تريده داخل المسارات الموجهة، مثل في استدعاء نطاق (scope) أو مجال أسماء (namespace):<syntaxhighlight lang="rails"> | |||
كما يمكنك استخدامها في أي مكان تريده داخل المسارات الموجهة، مثل في استدعاء نطاق (scope) أو مجال أسماء (namespace): | |||
namespace :articles do | namespace :articles do | ||
concerns :commentable | |||
end | end | ||
</syntaxhighlight> | |||
=== إنشاء مسارات وعناوين URL من الكائنات === | === إنشاء مسارات وعناوين URL من الكائنات === | ||
بالإضافة إلى استخدام مساعدين التوجيه، تستطيع Rails أيضًا إنشاء مسارات وعناوين URL من مصفوفة من المعاملات. على سبيل المثال، لنفترض أن لديك مجموعة المسارات الموجهة التالية: | بالإضافة إلى استخدام مساعدين التوجيه، تستطيع Rails أيضًا إنشاء مسارات وعناوين URL من مصفوفة من المعاملات. على سبيل المثال، لنفترض أن لديك مجموعة المسارات الموجهة التالية:<syntaxhighlight lang="rails"> | ||
resources :magazines do | resources :magazines do | ||
resources :ads | |||
end | end | ||
</syntaxhighlight>عند استخدام <code>magazine_ad_path</code>، يمكنك تمرير نسخ من <code>Magazine</code> و <code>Ad</code> بدلًا من المعرفات الرقمية <code>IDs</code>:<syntaxhighlight lang="rails"> | |||
عند استخدام | |||
<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %> | <%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %> | ||
</syntaxhighlight>يمكنك أيضًا استخدام <code>url_for</code> مع مجموعة من الكائنات، وسوف تحدد ريلز المسار الموجهة الذي تريده تلقائيًا:<syntaxhighlight lang="rails"> | |||
يمكنك أيضًا استخدام url_for مع مجموعة من الكائنات، وسوف تحدد | |||
<%= link_to 'Ad details', url_for([@magazine, @ad]) %> | <%= link_to 'Ad details', url_for([@magazine, @ad]) %> | ||
</syntaxhighlight>في هذه الحالة، سترى ريلز أن <code>magazine@</code> هو <code>Magazine</code> و <code>ad@</code> هو <code>Ad</code> وبالتالي ستستخدم المساعد <code>magazine_ad_path</code>. في المساعدين مثل <code>link_to</code>، يمكنك تحديد الكائن بدلًا من استدعاء <code>url_for</code> بالكامل:<syntaxhighlight lang="rails"> | |||
في هذه الحالة، سترى | |||
<%= link_to 'Ad details', [@magazine, @ad] %> | <%= link_to 'Ad details', [@magazine, @ad] %> | ||
</syntaxhighlight>إذا كنت تريد الارتباط بمجلة فقط:<syntaxhighlight lang="rails"> | |||
إذا كنت تريد الارتباط بمجلة فقط: | |||
<%= link_to 'Magazine details', @magazine %> | <%= link_to 'Magazine details', @magazine %> | ||
</syntaxhighlight>بالنسبة إلى الإجراءات الأخرى، تحتاج فقط إلى إدراج اسم الإجراء باعتباره العنصر الأول في المصفوفة:<syntaxhighlight lang="rails"> | |||
بالنسبة إلى الإجراءات الأخرى، تحتاج فقط إلى إدراج اسم الإجراء باعتباره العنصر الأول في المصفوفة: | |||
<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %> | <%= link_to 'Edit Ad', [:edit, @magazine, @ad] %> | ||
</syntaxhighlight>يتيح لك ذلك التعامل مع نسخ النماذج الخاصة بك كعناوين URL، وهي ميزة أساسية لاستخدام النمط كثير المورد. | |||
يتيح لك ذلك التعامل مع نسخ النماذج الخاصة بك كعناوين URL، وهي ميزة أساسية لاستخدام النمط كثير المورد. | |||
=== إضافة المزيد من الإجراءات RESTful === | === إضافة المزيد من الإجراءات RESTful === | ||
سطر 686: | سطر 514: | ||
==== إضافة مسارات الأعضاء ==== | ==== إضافة مسارات الأعضاء ==== | ||
لإضافة مسار موجه عضو، ما عليك سوى إضافة الكتلة member إلى كتلة الموارد resource: | لإضافة مسار موجه عضو، ما عليك سوى إضافة الكتلة <code>member</code> إلى كتلة الموارد <code>resource</code>:<syntaxhighlight lang="rails"> | ||
resources :photos do | resources :photos do | ||
member do | |||
get 'preview' | |||
end | |||
end | end | ||
</syntaxhighlight>سيتعرف هذا على /photos/1/preview مع GET، ويوجهه إلى الإجراء <code>preview</code> الذي يخص <code>PhotosController</code>، مع تمرير قيمة معرف المورد <code>id</code> في المعاملات <code>[:id]</code>. سيؤدي أيضًا إلى إنشاء <code>photos_preview_url</code> والمساعدين <code>photo_preview_path</code>. | |||
ضمن كتلة مسارات الأعضاء الموجهة، كل اسم مسار (route name) يحدد فعل HTTP سيُتعرَّف عليه. يمكنك استخدام get أو patch أو put أو post أو delete هنا. إذا لم يكن لديك العديد من مسارات الأعضاء الموجهة، فيمكنك أيضًا تمرير <code>:on</code> إلى المسار، وإلغاء الكتلة:<syntaxhighlight lang="rails"> | |||
ضمن كتلة مسارات الأعضاء الموجهة، كل اسم مسار (route name) يحدد فعل HTTP سيُتعرَّف عليه. يمكنك استخدام get أو patch أو put أو post أو delete هنا. إذا لم يكن لديك العديد من مسارات الأعضاء الموجهة، فيمكنك أيضًا تمرير :on إلى المسار، وإلغاء الكتلة: | |||
resources :photos do | resources :photos do | ||
get 'preview', on: :member | |||
end | end | ||
</syntaxhighlight>يمكنك ترك الخيار <code>:on</code>، إذ سيؤدي ذلك إلى إنشاء نفس مسار العضو باستثناء أن قيمة معرف المورد <code>id</code> ستكون متاحة في <code>[params[:photo_id</code> بدلًا من <code>[params[:id</code>. | |||
يمكنك ترك الخيار : | |||
==== إضافة مسارات التجميع ==== | ==== إضافة مسارات التجميع ==== | ||
لإضافة مسار موجه إلى المجموعة: | لإضافة مسار موجه إلى المجموعة:<syntaxhighlight lang="rails"> | ||
resources :photos do | resources :photos do | ||
collection do | |||
get 'search' | |||
end | |||
end | end | ||
</syntaxhighlight>سيؤدي هذا إلى تمكين ريلز للتعرف على مسارات مثل /photos/search باستخدام GET، والتوجيه إلى الإجراء <code>search</code> الذي يخص <code>PhotosController</code>. سيؤدي أيضًا إلى إنشاء مساعدي التوجيه <code>search_photos_url</code> و <code>search_photos_path</code>. | |||
كما هو الحال مع توجيهات الأعضاء (member routes)، يمكنك تمرير <code>:on</code> إلى توجيه بالشكل التالي:<syntaxhighlight lang="rails"> | |||
كما هو الحال مع توجيهات الأعضاء (member routes)، يمكنك تمرير :on إلى توجيه بالشكل التالي: | |||
resources :photos do | resources :photos do | ||
get 'search', on: :collection | |||
end | end | ||
</syntaxhighlight> | |||
==== إضافة توجيهات لإجراءات جديدة إضافية ==== | ==== إضافة توجيهات لإجراءات جديدة إضافية ==== | ||
يمكن إضافة إجراء جديد بديل باستخدام الاختصار :on بالشكل التالي: | يمكن إضافة إجراء جديد بديل باستخدام الاختصار :on بالشكل التالي:<syntaxhighlight lang="rails"> | ||
resources :comments do | resources :comments do | ||
get 'preview', on: :new | |||
end | end | ||
</syntaxhighlight>سيؤدي هذا إلى تمكين ريلز للتعرف على مسارات مثل /comments/new/preview باستخدام GET، وتوجيهها إلى الإجراء <code>preview</code> الذي يخص <code>CommentController</code>. سيؤدي أيضًا إلى إنشاء مساعدي التوجيه <code>preview_new_comment_url</code> و <code>preview_new_comment_path</code>. | |||
'''فائدة''': إذا وجدت نفسك تضيف العديد من الإجراءات الإضافية إلى مسار موجه ذي أهمية، فقد حان الوقت للتوقف وسؤال نفسك ما إذا كنت تموه عن وجود مورد آخر. | |||
فائدة: إذا وجدت نفسك تضيف العديد من الإجراءات الإضافية إلى مسار موجه ذي أهمية، فقد حان الوقت للتوقف وسؤال نفسك ما إذا كنت تموه عن وجود مورد آخر. | |||
== المسارات الموجهة غير كثيرة المورد (Non-Resourceful) == | == المسارات الموجهة غير كثيرة المورد (Non-Resourceful) == | ||
بالإضافة إلى توجيه الموارد، تتمتع | بالإضافة إلى توجيه الموارد، تتمتع ريلز بدعم قوي لتوجيه عناوين URL العشوائية إلى الإجراءات. هنا، لا يمكنك الحصول على مجموعات من التوجيهات التي تنشأ تلقائيًا من خلال توجيه الموارد. بدلاً من ذلك، يمكنك إعداد كل توجيه على حدة داخل تطبيقك. | ||
على الرغم من أنه يجب عليك عادة استخدام التوجيه كثير المورد (resourceful routing)، إلا أنه لا يزال هناك العديد من الأماكن التي يكون فيها التوجيه الأبسط أكثر ملاءمة. ليس هناك حاجة لمحاولة ارتداء كل جزء أخير من تطبيقك في إطار كثير المورد إذا لم يكن ذلك مناسبًا. | على الرغم من أنه يجب عليك عادة استخدام التوجيه كثير المورد (resourceful routing)، إلا أنه لا يزال هناك العديد من الأماكن التي يكون فيها التوجيه الأبسط أكثر ملاءمة. ليس هناك حاجة لمحاولة ارتداء كل جزء أخير من تطبيقك في إطار كثير المورد إذا لم يكن ذلك مناسبًا. | ||
على وجه الخصوص، يجعل التوجيه البسيط من السهل جدًا تعيين عناوين URL القديمة لإجراءات | على وجه الخصوص، يجعل التوجيه البسيط من السهل جدًا تعيين عناوين URL القديمة لإجراءات ريلز الجديدة. | ||
=== المعاملات المقيدة === | === المعاملات المقيدة === | ||
عند إعداد مسار عادي، فإنك تقدم سلسلة من الرموز التي تحددها | عند إعداد مسار عادي، فإنك تقدم سلسلة من الرموز التي تحددها ريلز إلى أجزاء من طلب HTTP الوارد. على سبيل المثال، ضع في اعتبارك هذا المسار الموجه:<syntaxhighlight lang="rails"> | ||
get 'photos(/:id)', to: :display | |||
get 'photos(/:id)', to: :display | </syntaxhighlight>إذا تمت معالجة طلب وارد من /photos/1 من خلال هذا التوجيه (لأنه لم يطابق أي توجيه سابق في الملف)، فستكون النتيجة استدعاء الإجراء <code>display</code> الذي يخص <code>PhotosController</code>، ولجعل المعامل النهائي "1"متاحًا بالشكل <code>[params[:id</code>. سيقوم هذا التوجيه أيضًا بتوجيه الطلب الوارد /photos إلى <code>DisplayController#display</code>، نظرًا لأن المُعرِّف <code>:id</code> هو مُعامل اختياري، يشار إليه بواسطة الأقواس. | ||
إذا تمت معالجة طلب وارد من /photos/1 من خلال هذا التوجيه (لأنه لم يطابق أي توجيه سابق في الملف)، فستكون النتيجة استدعاء الإجراء display الذي يخص | |||
=== الأجزاء الديناميكية === | === الأجزاء الديناميكية === | ||
يمكنك إعداد العديد من الأجزاء الديناميكية (Dynamic Segments) ضمن مسار موجه عادي حسب رغبتك. سيكون أي جزء متاحًا للعمل كجزء من params. إذا أعددت المسار الموجه التالي: | يمكنك إعداد العديد من الأجزاء الديناميكية (Dynamic Segments) ضمن مسار موجه عادي حسب رغبتك. سيكون أي جزء متاحًا للعمل كجزء من <code>params</code>. إذا أعددت المسار الموجه التالي:<syntaxhighlight lang="rails"> | ||
get 'photos/:id/:user_id', to: 'photos#show' | get 'photos/:id/:user_id', to: 'photos#show' | ||
</syntaxhighlight>سيرسل المسار الوارد /photos/1/2 إلى الإجراء <code>show</code> الخاص بـ <code>[PhotosController.params [:id</code>. سيكون <code>params[:id]</code> هو "1"، وسيكون <code>[params[:user_id</code> هو "2". | |||
'''فائدة''': بشكل افتراضي، لا تقبل الأجزاء الديناميكية النقاط، وهذا يرجع إلى استخدام النقطة كفاصل للمسارات الموجهة المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل جزء ديناميكي، أضف قيدًا يتجاوز هذا مثل <code>id: /[^\/]+/</code> الذي يسمح بأي شيء باستثناء الخط المستقيم المائل. | |||
فائدة: بشكل افتراضي، لا تقبل الأجزاء الديناميكية النقاط، وهذا يرجع إلى استخدام النقطة كفاصل للمسارات الموجهة المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل جزء ديناميكي، أضف قيدًا يتجاوز هذا مثل id: /[^\/]+/ الذي يسمح بأي شيء باستثناء الخط المستقيم المائل. | |||
=== الأجزاء الثابتة === | === الأجزاء الثابتة === | ||
يمكنك تحديد الأجزاء الثابتة (Static Segments) عند إنشاء مسار موجه من خلال عدم إلحاق النقطتين بالجزء fragment: | يمكنك تحديد الأجزاء الثابتة (Static Segments) عند إنشاء مسار موجه من خلال عدم إلحاق النقطتين بالجزء fragment:<syntaxhighlight lang="rails"> | ||
get 'photos/:id/with_user/:user_id', to: 'photos#show' | get 'photos/:id/with_user/:user_id', to: 'photos#show' | ||
</syntaxhighlight>يستجيب هذا المسار الموجه لمسارات مثل /photos/1/with_user/2. في هذه الحالة، ستكون | |||
المعاملات هي <code>{controller: 'photos'، action: 'show'، id: '1'، user_id: '2ٌ'}</code>. | |||
المعاملات هي {controller: 'photos'، action: 'show'، id: '1'، user_id: '2ٌ'}. | |||
=== سلسلة الاستعلام === | === سلسلة الاستعلام === | ||
ستشمل المعاملات أيضًا أي معاملات من سلسلة الاستعلام. على سبيل المثال، مع هذا المسار الموجه: | ستشمل المعاملات أيضًا أي معاملات من سلسلة الاستعلام. على سبيل المثال، مع هذا المسار الموجه:<syntaxhighlight lang="rails"> | ||
get 'photos/:id', to: 'photos#show' | get 'photos/:id', to: 'photos#show' | ||
</syntaxhighlight>سيرسل المسار الوارد /photos/1?user_id=2 إلى الإجراء <code>show</code> الخاص بوحدة تحكم <code>Photos</code>. إن <code>params</code> ستكون <code>{ controller: 'photos', action: 'show', id: '1', user_id: '2' }</code>. | |||
سيرسل المسار الوارد /photos/1?user_id=2 إلى الإجراء show الخاص بوحدة تحكم Photos. إن params ستكون { controller: 'photos', action: 'show', id: '1', user_id: '2' }. | |||
=== تحديد الافتراضات === | === تحديد الافتراضات === | ||
يمكنك تحديد الإعدادات الافتراضية في المسار من خلال توفير تجزئة (hash) للخيار :defaults. وينطبق هذا حتى على المعاملات التي لا تحددها كشرائح ديناميكية. فمثلًا: | يمكنك تحديد الإعدادات الافتراضية في المسار من خلال توفير تجزئة (hash) للخيار <code>:defaults</code>. وينطبق هذا حتى على المعاملات التي لا تحددها كشرائح ديناميكية. فمثلًا:<syntaxhighlight lang="rails"> | ||
get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' } | get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' } | ||
</syntaxhighlight>تطابق ريلز المسار photos/12 مع الإجراء <code>show</code> الذي يخص <code>showController</code>، وتعين <code>params[:format]</code> إلى "jpg". | |||
يمكنك أيضًا استخدام <code>defaults</code> في تنسيق الكتلة لتحديد الإعدادات الافتراضية لعناصر متعددة:<syntaxhighlight lang="rails"> | |||
يمكنك أيضًا استخدام defaults في تنسيق الكتلة لتحديد الإعدادات الافتراضية لعناصر متعددة: | |||
defaults format: :json do | defaults format: :json do | ||
resources :photos | |||
end | end | ||
</syntaxhighlight>'''ملاحظة''': لا يمكنك إلغاء القيم الافتراضية عبر معاملات الاستعلام وهذا يعود لأسباب أمنية. القيم الافتراضية الوحيدة التي يمكن تجاوزها هي الأجزاء الديناميكية عن طريق استبدالها في مسار URL. | |||
ملاحظة: لا يمكنك إلغاء القيم الافتراضية عبر معاملات الاستعلام وهذا يعود لأسباب أمنية. القيم الافتراضية | |||
=== تسمية المسارات الموجهة === | === تسمية المسارات الموجهة === | ||
يمكنك تحديد اسم لأي مسار موجه باستخدام الخيار :as: | يمكنك تحديد اسم لأي مسار موجه باستخدام الخيار :as:<syntaxhighlight lang="rails"> | ||
get 'exit', to: 'sessions#destroy', as: :logout | |||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء <code>logout_path</code> و <code>logout_url</code> كمساعدين مسميين في تطبيقك. وسيؤدي استدعاء <code>loging_path</code> إلى إعادة /exit. | |||
يمكنك أيضًا استخدام هذا لتجاوز توابع التوجيه المحددة بواسطة الموارد كما يلي:<syntaxhighlight lang="rails"> | |||
get ':username', to: 'users#show', as: :user | |||
</syntaxhighlight>سيحدد هذا التابع <code>user_path</code> الذي سيتاح في وحدات التحكم، والمساعدين والواجهات التي ستنتقل إلى مسار مثل /bob. داخل الخيار <code>show</code> الخاص بـ <code>UsersController</code>، تحتوي <code>[params[:username</code> على اسم المستخدم للمستخدم. غير <code>:username</code> في تعريف المسار الموجه إذا كنت لا تريد أن يكون اسم المعامل <code>:username</code>. | |||
يمكنك أيضًا استخدام هذا لتجاوز توابع التوجيه المحددة بواسطة الموارد كما يلي: | |||
get ':username', to: 'users#show', as: :user | |||
سيحدد هذا التابع user_path الذي سيتاح في وحدات التحكم، والمساعدين والواجهات التي ستنتقل إلى مسار مثل /bob. داخل الخيار show الخاص بـ | |||
=== قيود فعل HTTP === | === قيود فعل HTTP === | ||
بشكل عام، يجب عليك استخدام التوابع get و post و put و patch و delete لتقييد توجيه إلى فعل معين. يمكنك استخدام التابع match مع الخيار :via لمطابقة أفعال متعددة في وقت واحد: | بشكل عام، يجب عليك استخدام التوابع get و post و put و patch و delete لتقييد توجيه إلى فعل معين. يمكنك استخدام التابع <code>match</code> مع الخيار <code>:via</code> لمطابقة أفعال متعددة في وقت واحد:<syntaxhighlight lang="rails"> | ||
match 'photos', to: 'photos#show', via: [:get, :post] | |||
</syntaxhighlight>يمكنك مطابقة جميع الأفعال إلى مسار معين باستخدام <code>via: :all</code> كما يلي:<syntaxhighlight lang="rails"> | |||
match 'photos', to: 'photos#show', via: :all | |||
</syntaxhighlight>'''ملاحظة''': توجيه كل من طلبيات GET و POST إلى إجراء واحد له آثار متعلقة بالأمان. بشكل عام، يجب تجنب توجيه جميع الأفعال إلى أي إجراء ما لم يكن لديك سبب وجيه لذلك. | |||
'''ملاحظة''': لن تتحقق طلبية GET في ريلز من رمز CSRF (اختصار للعبارة cross-site request forgery، وهي الهجمات مُزوّرة الطلب عبر المواقع). يجب ألا تكتب أبدًا إلى قاعدة البيانات من طلبيات GET؛ لمزيد من المعلومات، انظر دليل الأمان الخاص بإجراءات CSRF المضادة. | |||
=== قيود الجزء (Segment Constraints) === | === قيود الجزء (Segment Constraints) === | ||
يمكنك استخدام الخيار :constraints لفرض تنسيق لجزء ديناميكي بالشكل التالي: | يمكنك استخدام الخيار <code>:constraints</code> لفرض تنسيق لجزء ديناميكي بالشكل التالي:<syntaxhighlight lang="rails"> | ||
get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ } | get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ } | ||
</syntaxhighlight>يطابق هذا المسار الموجه مسارات مثل /photos/A12345، ولكن ليس /photos/893. يمكنك التعبير بشكل أكثر دقة عن نفس التوجيه بهذه الطريقة:<syntaxhighlight lang="rails"> | |||
يطابق هذا المسار الموجه مسارات مثل /photos/A12345، ولكن ليس /photos/893. يمكنك التعبير بشكل أكثر دقة عن نفس التوجيه بهذه الطريقة: | |||
get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/ | get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/ | ||
</syntaxhighlight>تأخذ <code>:constraints</code> تعبيرات نمطية مع القيود التي لا يمكن أن تستخدم مثبتات التعبير النمطي (regexp anchors). على سبيل المثال، لن يعمل التوجيه التالي:<syntaxhighlight lang="rails"> | |||
تأخذ :constraints تعبيرات نمطية مع القيود التي لا يمكن أن تستخدم مثبتات التعبير النمطي (regexp anchors). على سبيل المثال، لن يعمل التوجيه التالي: | |||
get '/:id', to: 'articles#show', constraints: { id: /^\d/ } | get '/:id', to: 'articles#show', constraints: { id: /^\d/ } | ||
</syntaxhighlight>ومع ذلك، لاحظ أنك لست بحاجة إلى استخدام نقاط تثبيت لأن جميع المسارات الموجهة المثبتة في البداية. | |||
على سبيل المثال، تسمح التوجيهات التالية لـ <code>articles</code> التي لها قيم <code>to_param</code> مثل <code>1-hello-world</code> والتي تبدأ دائمًا برقم ولـ <code>users</code> التي لها قيم <code>to_param</code> مثل <code>david</code> التي لا تبدأ برقم بمشاركة مجال الاسم الجذر (root namespace):<syntaxhighlight lang="rails"> | |||
على سبيل المثال، تسمح التوجيهات التالية لـ articles التي لها قيم to_param مثل 1-hello-world والتي تبدأ دائمًا برقم ولـ users التي لها قيم to_param مثل david التي لا تبدأ برقم بمشاركة مجال الاسم الجذر (root namespace): | |||
get '/:id', to: 'articles#show', constraints: { id: /\d.+/ } | get '/:id', to: 'articles#show', constraints: { id: /\d.+/ } | ||
get '/:username', to: 'users#show' | get '/:username', to: 'users#show' | ||
</syntaxhighlight> | |||
=== قيود على أساس الطلب === | === قيود على أساس الطلب === | ||
يمكنك أيضًا تقييد مسار موجه استنادًا إلى أي تابع في كائن الطلب Request التي يعيد سلسلة نصية. | يمكنك أيضًا تقييد مسار موجه استنادًا إلى أي تابع في كائن الطلب <code>Request</code> التي يعيد سلسلة نصية. | ||
يمكنك تحديد القيد على أساس الطلب بنفس الطريقة التي تحدد بها قيد الجزء (segment constraint):<syntaxhighlight lang="rails"> | |||
get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' } | get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' } | ||
</syntaxhighlight>يمكنك أيضًا تحديد القيود في نموذج الكتلة:<syntaxhighlight lang="rails"> | |||
يمكنك أيضًا تحديد القيود في نموذج الكتلة: | |||
namespace :admin do | namespace :admin do | ||
constraints subdomain: 'admin' do | |||
resources :photos | |||
end | |||
end | end | ||
</syntaxhighlight>'''ملاحظة''': تعمل قيود الطلب عن طريق استدعاء تابع في كائن الطلب <code>Request</code> يحمل نفس الاسم مثل مفتاح التجزئة (hash) ثم مقارنة القيمة المعادة بقيمة الجدول Hash. لذلك، يجب أن تتطابق قيم القيد مع نوع إرجاع تابع كائن الطلب المقابل. على سبيل المثال: <code>{ 'constraints: { subdomain: 'api</code> سيطابق نطاقًا فرعيًا لواجهة برمجة التطبيق كما هو متوقع، ولكن لن يكون باستخدام رمز مثل | |||
<code>{ constraints: { subdomain: :api</code>، نظرًا لأن <code>request.subdomain</code> يعرض <code>"api"</code> كسلسلة نصية. | |||
'''ملاحظة''': هناك استثناء للقيد <code>format</code> وهو في حين أنه تابع في كائن الطلب <code>Request</code>، وهو أيضًا معامل اختياري ضمني في كل مسار. يكون لقيود الشريحة الأسبقية وتطبق قيود التنسيق فقط عند فرضها عبر التجزئة. على سبيل المثال، <code>get 'foo', constraints: { format: 'json' }</code> سيطابق <code>GET /foo</code> لأن التنسيق اختياري بشكل افتراضي. ومع ذلك، يمكنك استخدام تعابير lambda مثل <code>{ get 'foo', constraints: lambda { |req| req.format == :json</code> وسيتطابق مسار التوجيه مع طلبيات JSON الصريحة فقط. | |||
ملاحظة: هناك استثناء للقيد format وهو في حين أنه تابع في كائن الطلب | |||
لأن التنسيق اختياري بشكل افتراضي. ومع ذلك، يمكنك استخدام تعابير lambda مثل | |||
{ get 'foo', constraints: lambda { |req| req.format == :json وسيتطابق التوجيه مع طلبيات JSON الصريحة فقط. | |||
=== القيود المتقدمة === | === القيود المتقدمة === | ||
إذا كان لديك قيد أكثر تقدمًا، يمكنك توفير كائن يستجيب إلى matches? التي يجب أن تستخدمها | إذا كان لديك قيد أكثر تقدمًا، يمكنك توفير كائن يستجيب إلى <code>matches?</code> التي يجب أن تستخدمها ريلز. لنفترض أنك تريد توجيه جميع المستخدمين في القائمة السوداء إلى <code>BlacklistController</code>، يمكنك القيام بذلك بالشكل التالي:<syntaxhighlight lang="rails"> | ||
class BlacklistConstraint | class BlacklistConstraint | ||
def initialize | |||
@ips = Blacklist.retrieve_ips | |||
end | |||
def matches?(request) | |||
@ips.include?(request.remote_ip) | |||
end | |||
end | end | ||
Rails.application.routes.draw do | Rails.application.routes.draw do | ||
get '*path', to: 'blacklist#index', | |||
constraints: BlacklistConstraint.new | |||
end | end | ||
</syntaxhighlight>يمكنك أيضا تحديد القيود على أنها تعابير lambda:<syntaxhighlight lang="rails"> | |||
يمكنك أيضا تحديد القيود على أنها تعابير lambda: | |||
Rails.application.routes.draw do | Rails.application.routes.draw do | ||
get '*path', to: 'blacklist#index', | |||
constraints: lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) } | |||
end | end | ||
</syntaxhighlight>كل من التابع <code>matches?</code> وتعابير lambda تحصل على كائن الطلب <code>Request</code> كوسيط. | |||
كل من | |||
=== التوجيه النمطي والأجزاء المتطابقة بالمحارف الخاصة === | === التوجيه النمطي والأجزاء المتطابقة بالمحارف الخاصة === | ||
التوجيه النمطي (Route globbing) هو طريقة لتحديد أنه يجب مطابقة معامل معين مع جميع الأجزاء المتبقية من المسار. فمثلًا: | التوجيه النمطي (Route globbing) هو طريقة لتحديد أنه يجب مطابقة معامل معين مع جميع الأجزاء المتبقية من المسار. فمثلًا:<syntaxhighlight lang="rails"> | ||
get 'photos/*other', to: 'photos#unknown' | get 'photos/*other', to: 'photos#unknown' | ||
</syntaxhighlight>سيطابق هذا التوجيه المسار photos/12 أو /photos/long/path/to/12 مع تعيين <code>[params[:other</code> إلى "12" أو "long/path/to/12". تسمى الأجزاء المسبوقة بالرمز <code>*</code> باسم "الأجزاء المتطابقة بالمحارف الخاصة" (wildcard segments). | |||
يمكن أن تظهر الأجزاء المتطابقة بالمحارف الخاصة في أي مكان في المسار. فمثلًا:<syntaxhighlight lang="rails"> | |||
يمكن أن تظهر الأجزاء المتطابقة بالمحارف الخاصة في أي مكان في المسار. فمثلًا: | |||
get 'books/*section/:title', to: 'books#show' | get 'books/*section/:title', to: 'books#show' | ||
</syntaxhighlight>من شأنه أن يطابق books/some/section/last-words-a-memoir مع <code>[params[:section</code> الذي يساوي 'some/section'، ومع <code>[params [:title</code> الذي يساوي 'last-words-a-memoir'. | |||
من الناحية الفنية، يمكن أن يحتوي المسار على أكثر من جزء واحدة متطابق. يعين المطابق (matcher) الأجزاء إلى معاملات بطريقة بديهية. فمثلًا:<syntaxhighlight lang="rails"> | |||
من الناحية الفنية، يمكن أن يحتوي المسار على أكثر من جزء واحدة متطابق. يعين المطابق (matcher) الأجزاء إلى معاملات بطريقة بديهية. فمثلًا: | |||
get '*a/foo/*b', to: 'test#index' | get '*a/foo/*b', to: 'test#index' | ||
</syntaxhighlight>سيطابق zoo/woo/foo/bar/baz مع <code>[params[:a</code> الذي يساوي 'zoo/woo'، ومع <code>[params[:b</code> الذي يساوي 'bar/baz'. | |||
'''ملاحظة''': عبر طلب '/foo/bar.json'، ستكون <code>[params[:pages</code> مساوية لـ '/foo/bar' مع تنسيق طلب JSON. إذا كنت تريد استعادة سلوك الإصدار 3.0.x القديم، فيمكنك توفير <code>format: false</code> بالشكل التالي:<syntaxhighlight lang="rails"> | |||
get '*pages', to: 'pages#show', format: false | get '*pages', to: 'pages#show', format: false | ||
</syntaxhighlight>إذا كنت تريد جعل جزء التنسيق إلزاميًا، وبذلك لا يمكن حذفه، فيمكنك توفير <code>format: true</code> بالشكل التالي:<syntaxhighlight lang="rails"> | |||
إذا كنت تريد جعل جزء التنسيق إلزاميًا، وبذلك لا يمكن حذفه، فيمكنك توفير format: true بالشكل التالي: | |||
get '*pages', to: 'pages#show', format: true | get '*pages', to: 'pages#show', format: true | ||
</syntaxhighlight> | |||
=== إعادة التوجيه === | === إعادة التوجيه === | ||
يمكنك إعادة توجيه (redirect) أي مسار إلى مسار آخر باستخدام مساعد إعادة التوجيه redirect في المسار الموجه الخاص بك: | يمكنك إعادة توجيه (redirect) أي مسار إلى مسار آخر باستخدام مساعد إعادة التوجيه <code>redirect</code> في المسار الموجه الخاص بك:<syntaxhighlight lang="rails"> | ||
get '/stories', to: redirect('/articles') | get '/stories', to: redirect('/articles') | ||
</syntaxhighlight>يمكنك أيضًا إعادة استخدام أجزاء ديناميكية من المطابقة في المسار لإعادة التوجيه إلى:<syntaxhighlight lang="rails"> | |||
يمكنك أيضًا إعادة استخدام أجزاء ديناميكية من المطابقة في المسار لإعادة التوجيه إلى: | |||
get '/stories/:name', to: redirect('/articles/%{name}') | get '/stories/:name', to: redirect('/articles/%{name}') | ||
</syntaxhighlight>يمكنك أيضًا توفير حظر لإعادة التوجيه، والذي يتلقى معاملات المسار الرمزية وكائن الطلب <code>Request</code>:<syntaxhighlight lang="rails"> | |||
يمكنك أيضًا توفير حظر لإعادة التوجيه، والذي يتلقى معاملات المسار الرمزية وكائن الطلب Request: | |||
get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" } | get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" } | ||
get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" } | get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" } | ||
</syntaxhighlight>يرجى ملاحظة أن إعادة التوجيه الافتراضية هي عملية إعادة توجيه 301 "تم نقلها بشكل دائم" (Moved Permanently). ضع في اعتبارك أن بعض متصفحات الويب أو الخوادم الوسيطة (proxy servers) ستخزن هذا النوع من إعادة التوجيه، مما يجعل الصفحة القديمة غير قابلة للوصول. يمكنك استخدام الخيار <code>:status</code> لتغيير حالة الاستجابة:<syntaxhighlight lang="rails"> | |||
يرجى ملاحظة أن إعادة التوجيه الافتراضية هي عملية إعادة توجيه 301 "تم نقلها بشكل دائم" (Moved Permanently). ضع في اعتبارك أن بعض متصفحات الويب أو الخوادم الوسيطة (proxy servers) ستخزن هذا النوع من إعادة التوجيه، مما يجعل الصفحة القديمة غير قابلة للوصول. يمكنك استخدام الخيار :status لتغيير حالة الاستجابة: | |||
get '/stories/:name', to: redirect('/articles/%{name}', status: 302) | get '/stories/:name', to: redirect('/articles/%{name}', status: 302) | ||
</syntaxhighlight>في جميع هذه الحالات، إذا لم تقدم المضيف الأساسي (<nowiki>http://www.example.com)،</nowiki> فستأخذ ريلز هذه التفاصيل من الطلب الحالي. | |||
في جميع هذه الحالات، إذا لم تقدم المضيف الأساسي (<nowiki>http://www.example.com)،</nowiki> فستأخذ | |||
=== التوجيه إلى تطبيقات Rack === | === التوجيه إلى تطبيقات Rack === | ||
بدلاً من سلسلة نصية مثل 'articles#index'، والتي تتطابق مع الإجراء index في | بدلاً من سلسلة نصية مثل <code>'articles#index'</code>، والتي تتطابق مع الإجراء <code>index</code> في <code>ArticlesController</code>، يمكنك تحديد أي تطبيق Rack كنقطة نهاية للمطابق:<syntaxhighlight lang="rails"> | ||
match '/application.js', to: MyRackApp, via: :all | |||
match '/application.js', to: MyRackApp, via: :all | </syntaxhighlight>طالما يستجيب <code>MyRackApp</code> لاستدعاء ويعيد <code>[status, headers, body]</code>، لن يعرف جهاز التوجيه الفرق بين تطبيق Rack والإجراء. هذا هو الاستخدام المناسب لـ <code>via: :all</code>، كما تريد السماح لتطبيق Rack الخاص بك بالتعامل مع جميع الأفعال التي تراها مناسبة. | ||
طالما يستجيب MyRackApp لاستدعاء ويعيد [status, headers, body]، لن يعرف جهاز التوجيه الفرق بين تطبيق Rack والإجراء. هذا هو الاستخدام المناسب لـ via: : | |||
ملاحظة: يوسع 'articles#index' فعليًا إلى (ArticlesController.action(: | '''ملاحظة''': يوسع <code>'articles#index'</code> فعليًا إلى <code>(ArticlesController.action(:index</code>، التي تُرجع تطبيق Rack صالحًا. | ||
إذا قمت بتحديد تطبيق Rack كنقطة نهاية للمطابقة، فتذكر أنَّ التوجيه لن يتغير في تطبيق الاستلام. مع التوجيه التالي، يجب أن يتوقع تطبيق Rack أن يكون المسار هو /admin:<syntaxhighlight lang="rails"> | |||
match '/admin', to: AdminApp, via: :all | |||
</syntaxhighlight>إذا كنت تفضل أن يتلقى تطبيق Rack طلبات على المسار الجذر بدلًا من ذلك، فاستخدم <code>mount</code>:<syntaxhighlight lang="rails"> | |||
mount AdminApp, at: '/admin' | mount AdminApp, at: '/admin' | ||
</syntaxhighlight> | |||
=== استخدام الجذر === | === استخدام الجذر === | ||
يمكنك تحديد ما يجب أن تسلكه Rails عند توجيه '/' باستخدام التابع root: | يمكنك تحديد ما يجب أن تسلكه Rails عند توجيه '/' باستخدام التابع <code>root</code>:<syntaxhighlight lang="rails"> | ||
root to: 'pages#main' | root to: 'pages#main' | ||
root 'pages#main' # shortcut for the abov | |||
</syntaxhighlight>يجب وضع مسار الجذر أعلى الملف، لأنه المسار الأكثر شيوعًا ويجب مطابقته أولاً. | |||
'''ملاحظة''': يوجه مسار الجذر فقط طلبيات GET إلى الإجراء. | |||
ملاحظة: يوجه مسار الجذر فقط طلبيات GET إلى الإجراء. | |||
يمكنك أيضًا استخدام الجذر داخل مجالات الأسماء والنطاقات أيضًا. فمثلًا:<syntaxhighlight lang="rails"> | |||
namespace :admin do | namespace :admin do | ||
root to: "admin#index" | |||
end | end | ||
root to: "home#index" | root to: "home#index" | ||
</syntaxhighlight> | |||
=== توجيهات محارف يونيكود === | === توجيهات محارف يونيكود === | ||
يمكنك تحديد توجيهات محارف يونيكود مباشرةً. فمثلًا: | يمكنك تحديد توجيهات محارف يونيكود مباشرةً. فمثلًا:<syntaxhighlight lang="rails"> | ||
get 'こんにちは', to: 'welcome#index' | get 'こんにちは', to: 'welcome#index' | ||
</syntaxhighlight> | |||
=== التوجيهات المباشرة === | === التوجيهات المباشرة === | ||
يمكنك إنشاء مساعدين مخصصين لعناوين URL مباشرةً. فمثلًا: | يمكنك إنشاء مساعدين مخصصين لعناوين URL مباشرةً. فمثلًا:<syntaxhighlight lang="rails"> | ||
direct :homepage do | direct :homepage do | ||
"http://www.rubyonrails.org" | |||
end | end | ||
# >> homepage_url | |||
# => "http://www.rubyonrails.org" | |||
</syntaxhighlight>يجب أن تعيد الكتلة وسيطًا صالحًا للتابع <code>url_for</code>. لذلك، يمكنك تمرير سلسلة URL صحيحة، أو جدول Hash، أو مصفوفة، أو نسخة من [[Rails/active model|Active Model]]، أو صنف من [[Rails/active model|Active Model]]: <syntaxhighlight lang="rails"> | |||
يجب أن تعيد الكتلة وسيطًا صالحًا للتابع url_for. لذلك، يمكنك تمرير سلسلة URL صحيحة، أو | |||
direct :commentable do |model| | direct :commentable do |model| | ||
[ model, anchor: model.dom_id ] | |||
end | end | ||
direct :main do | direct :main do | ||
{ controller: 'pages', action: 'index', subdomain: 'www' } | |||
end | end | ||
</syntaxhighlight> | |||
=== استخدام resolve === | === استخدام <code>resolve</code> === | ||
يسمح التابع resolve بتخصيص تعيينات متعددة الأشكال (polymorphic mapping) للنماذج. فمثلًا: | يسمح التابع <code>resolve</code> بتخصيص تعيينات متعددة الأشكال (polymorphic mapping) للنماذج. فمثلًا:<syntaxhighlight lang="rails"> | ||
resource :basket | resource :basket | ||
resolve("Basket") { [:basket] } | resolve("Basket") { [:basket] } | ||
</syntaxhighlight><syntaxhighlight lang="rails"> | |||
<%= form_for @basket do |form| %> | <%= form_for @basket do |form| %> | ||
<!-- basket form --> | |||
<% end %> | <% end %> | ||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء عنوان URL هو /basket بدلًا من العنوان /baskets/:id المعتاد. | |||
سيؤدي ذلك إلى إنشاء عنوان URL هو /basket بدلًا من العنوان /baskets/:id المعتاد. | |||
== تخصيص التوجيهات كثيرة الموارد == | == تخصيص التوجيهات كثيرة الموارد == | ||
في حين أن التوجيهات والمساعدات الافتراضية التي أنشئت بواسطة resources :articles عادةً ما تخدمك جيدًا، فقد تحتاج إلى تخصيصها بطريقة ما. تسمح لك | في حين أن التوجيهات والمساعدات الافتراضية التي أنشئت بواسطة <code>resources :articles</code> عادةً ما تخدمك جيدًا، فقد تحتاج إلى تخصيصها بطريقة ما. تسمح لك ريلز بتخصيص أي جزء عام من المساعدين كثيري الموارد (resourceful helpers). | ||
=== تحديد وحدة تحكم لاستخدامها === | === تحديد وحدة تحكم لاستخدامها === | ||
يتيح لك الخيار :controller تحديد وحدة تحكم بشكل صريح لاستخدامها في المورد. فمثلًا: | يتيح لك الخيار <code>:controller</code> تحديد وحدة تحكم بشكل صريح لاستخدامها في المورد. فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :photos, controller: 'images' | |||
</syntaxhighlight>سيتعرف على المسارات الواردة التي تبدأ بـ /photos ولكن سيوجه إلى وحدة التحكم في <code>Images</code>: | |||
سيتعرف على المسارات الواردة التي تبدأ بـ /photos ولكن سيوجه إلى وحدة التحكم في Images: | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم#الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/photos | |/photos | ||
|images#index | |<code>images#index</code> | ||
|photos_path | |<code>photos_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/new | |/photos/new | ||
|images#new | |<code>images#new</code> | ||
|new_photo_path | |<code>new_photo_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/photos | |/photos | ||
|images#create | |<code>images#create</code> | ||
|photos_path | |<code>photos_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id | |/photos/:id | ||
|images#show | |<code>images#show</code> | ||
|photo_path(:id) | |<code>photo_path(:id)</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id/edit | |/photos/:id/edit | ||
|images#edit | |<code>images#edit</code> | ||
|edit_photo_path(:id) | |<code>edit_photo_path(:id)</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/photos/:id | |/photos/:id | ||
|images#update | |<code>images#update</code> | ||
|photo_path(:id) | |<code>photo_path(:id)</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/photos/:id | |/photos/:id | ||
|images#destroy | |<code>images#destroy</code> | ||
|photo_path(:id) | |<code>photo_path(:id)</code> | ||
|} | |} | ||
ملاحظة: استخدم photos_photo و new_photo_path وما إلى ذلك لإنشاء مسارات لهذا المورد. | '''ملاحظة''': استخدم <code>photos_photo</code> و <code>new_photo_path</code> وما إلى ذلك لإنشاء مسارات لهذا المورد. | ||
هذا سوف يوجهه إلى وحدة التحكم Admin::UserPermissions. | بالنسبة لوحدات تحكم ذات مجال أسماء (namespaced controllers)، يمكنك استخدام تدوين المجلد (directory notation). فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :user_permissions, controller: 'admin/user_permissions' | |||
</syntaxhighlight>هذا سوف يوجهه إلى وحدة التحكم <code>Admin::UserPermissions</code>. | |||
ملاحظة: تدوين المجلد مدعومٌ فقط. يمكن أن يؤدي تحديد وحدة التحكم بتدوين Ruby الثابت | '''ملاحظة''': تدوين المجلد مدعومٌ فقط. يمكن أن يؤدي تحديد وحدة التحكم بتدوين [[Ruby|روبي]] الثابت | ||
(مثل controller: 'Admin::UserPermissions') إلى مشاكل في التوجيه ينتج عنها تحذيرات. | (مثل <code>controller: 'Admin::UserPermissions'</code>) إلى مشاكل في التوجيه ينتج عنها تحذيرات. | ||
=== تحديد القيود === | === تحديد القيود === | ||
يمكنك استخدام الخيار :constraints لتحديد التنسيق المطلوب على المعرّف id الضمني. فمثلًا: | يمكنك استخدام الخيار <code>:constraints</code> لتحديد التنسيق المطلوب على المعرّف <code>id</code> الضمني. فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ } | |||
< | </syntaxhighlight>يقيد هذا الاعلان المعامل <code>id:</code> ليطابق التعبير المعتاد الموفر. لذلك، في هذه الحالة، لم يعد جهاز التوجيه يتطابق مع /photos/1 مع هذا المسار. بدلًا من ذلك، إنَّ /photos/RR27 هي من ستتطابق. | ||
يقيد هذا الاعلان المعامل id: ليطابق التعبير المعتاد الموفر. لذلك، في هذه الحالة، لم يعد جهاز التوجيه يتطابق مع /photos/1 مع هذا المسار. بدلًا من ذلك، إنَّ /photos/RR27 هي من ستتطابق. | |||
يمكنك تحديد قيد واحد لتطبيقه على عدد من المسارات باستخدام نموذج الكتلة:<syntaxhighlight lang="rails"> | |||
constraints(id: /[A-Z][A-Z][0-9]+/) do | constraints(id: /[A-Z][A-Z][0-9]+/) do | ||
resources :photos | |||
resources :accounts | |||
end | |||
</syntaxhighlight>'''ملاحظة''': بالطبع، يمكنك استخدام القيود الأكثر تقدمًا المتوفرة في المسارات غير كثيرة الموارد في هذا السياق. | |||
'''فائدة''': بشكل افتراضي، لا يقبل المعامل <code>:id</code> النقاط وذلك لأن النقطة تستخدم كفاصل للمسارات المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل <code>:id</code>، فأدخل قيدًا يتجاوز هذا مثل <code>id: /[^\/]+/</code> يسمح بأي شيء باستثناء الشرطة المائلة. | |||
فائدة: بشكل افتراضي، لا يقبل المعامل :id النقاط وذلك لأن النقطة تستخدم كفاصل للمسارات المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل : | |||
=== تجاوز المساعدين المسماة === | === تجاوز المساعدين المسماة === | ||
يسمح لك الخيار :as بتجاوز التسمية العادية لمساعدي مسار معين. فمثلًا: | يسمح لك الخيار <code>:as</code> بتجاوز التسمية العادية لمساعدي مسار معين. فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :photos, as: 'images' | |||
</syntaxhighlight>سوف يتعرف على المسارات الواردة التي تبدأ بـ /photos ويوجه الطلبات إلى <code>PhotosController</code>، ولكن استخدم الخيار <code>:as</code> لتسمية المساعدين. | |||
سوف يتعرف على المسارات الواردة التي تبدأ بـ /photos ويوجه الطلبات إلى | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/photos | |/photos | ||
|photos#index | |<code>photos#index</code> | ||
|images_path | |<code>images_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/new | |/photos/new | ||
|photos#new | |<code>photos#new</code> | ||
|new_image_path | |<code>new_image_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/photos | |/photos | ||
|photos#create | |<code>photos#create</code> | ||
|images_path | |<code>images_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id | |/photos/:id | ||
|photos#show | |<code>photos#show</code> | ||
|image_path(:id) | |<code>image_path(:id)</code> | ||
|- | |- | ||
|GET | |GET | ||
|/photos/:id/edit | |/photos/:id/edit | ||
|photos#edit | |<code>photos#edit</code> | ||
|edit_image_path(:id) | |<code>edit_image_path(:id)</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/photos/:id | |/photos/:id | ||
|photos#update | |<code>photos#update</code> | ||
|image_path(:id) | |<code>image_path(:id)</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/photos/:id | |/photos/:id | ||
|photos#destroy | |<code>photos#destroy</code> | ||
|image_path(:id) | |<code>image_path(:id)</code> | ||
|} | |} | ||
=== استبدال الأجزاء الجديدة وتعديلها === | === استبدال الأجزاء الجديدة وتعديلها === | ||
يتيح لك الخيار :path_names استبدال الأجزاء الجديدة وتعديلها تلقائيًا في المسارات: | يتيح لك الخيار <code>:path_names</code> استبدال الأجزاء الجديدة وتعديلها تلقائيًا في المسارات:<syntaxhighlight lang="rails"> | ||
resources :photos, path_names: { new: 'make', edit: 'change' } | |||
</syntaxhighlight>قد يتسبب هذا في التعرف على المسارات مثل:<syntaxhighlight lang="text"> | |||
قد يتسبب هذا في التعرف على المسارات مثل: | |||
/photos/make | /photos/make | ||
/photos/1/change | /photos/1/change | ||
</syntaxhighlight>'''ملاحظة''': لا تتغيير أسماء الإجراءات الفعلية بواسطة هذا الخيار. سيستمر المساران المعروضان في مسار التوجيه إلى الإجراءات الجديدة وتعديلها. | |||
'''فائدة''': إذا وجدت نفسك ترغب في تغيير هذا الخيار بشكل موحد لجميع مسارات التوجيه لديك، فيمكنك استخدام النطاق.<syntaxhighlight lang="rails"> | |||
فائدة: إذا وجدت نفسك ترغب في تغيير هذا الخيار بشكل موحد لجميع مسارات التوجيه لديك، فيمكنك استخدام النطاق. | |||
scope path_names: { new: 'make' } do | scope path_names: { new: 'make' } do | ||
# rest of your routes | |||
end | end | ||
</syntaxhighlight> | |||
=== إضافة بادئة لمساعدي مسار التوجيه المسمى === | === إضافة بادئة لمساعدي مسار التوجيه المسمى === | ||
يمكنك استخدام الخيار :as لإضافة بادئة لمساعدي مسار التوجيه المسمى الذي تُنشئُه | يمكنك استخدام الخيار <code>:as</code> لإضافة بادئة لمساعدي مسار التوجيه المسمى الذي تُنشئُه ريلز لمسار التوجيه. استخدم هذا الخيار لمنع تضارب الأسماء بين المسارات باستخدام نطاق مسار. فمثلًا:<syntaxhighlight lang="rails"> | ||
scope 'admin' do | scope 'admin' do | ||
resources :photos, as: 'admin_photos' | |||
end | end | ||
resources :photos | resources :photos | ||
</syntaxhighlight>سيوفر ذلك مساعدين لمسارات التوجيه، مثل <code>admin_photos_path</code> و <code>new_admin_photo_path</code> وما إلى ذلك. | |||
لإضافة بادئة لمجموعة من مساعدي مسارات التوجيه، استخدم الخيار <code>:as</code> مع النطاق:<syntaxhighlight lang="rails"> | |||
لإضافة بادئة لمجموعة من مساعدي مسارات التوجيه، استخدم الخيار :as مع النطاق: | |||
scope 'admin', as: 'admin' do | scope 'admin', as: 'admin' do | ||
resources :photos, :accounts | |||
end | end | ||
resources :photos, :accounts | resources :photos, :accounts | ||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء مسارات مثل <code>admin_photos_path</code> و <code>admin_accounts_path</code> والتي تعين /admin /photos و /admin/accounts على التوالي. | |||
'''ملاحظة''': سيضيف نطاق مجال الأسماء تلقائيًا الخيار <code>:as</code> بالإضافة إلى البادئات <code>:module</code> و <code>:path</code>. | |||
ملاحظة: سيضيف نطاق مجال الأسماء تلقائيًا الخيار :as بالإضافة إلى البادئات :module و :path. | |||
يمكن إضافة بادئة لمسارات التوجيه مع معامل مسمى أيضًا:<syntaxhighlight lang="rails"> | |||
scope ':username' do | scope ':username' do | ||
resources :articles | |||
end | end | ||
</syntaxhighlight>سيزودك هذا بعناوين URL مثل /bob/articles/1 وسيسمح لك بمراجعة الجزء <code>username</code> من المسار | |||
بالشكل <code>[params[:username</code> في وحدات التحكم والمساعدين والواجهات. | |||
بالشكل [params[:username في وحدات التحكم والمساعدين والواجهات. | |||
=== تقييد مسارات التوجيه التي أنشئت === | === تقييد مسارات التوجيه التي أنشئت === | ||
بشكل افتراضي، تنشئ | بشكل افتراضي، تنشئ ريلز مسارات توجيه للإجراءات الافتراضية السبعة (<code>index</code>، و <code>show</code>، و <code>new</code>، و <code>create</code>، و <code>edit</code>، و <code>update</code>، و <code>destroy</code>) لكل مسار RESTful في التطبيق الخاص بك. يمكنك استخدام الخيارات <code>:only</code> و <code>:except</code> لضبط هذا السلوك. الخيار <code>:only</code> يخبر ريلز بإنشاء المسارات المحددة فقط:<syntaxhighlight lang="rails"> | ||
resources :photos, only: [:index, :show] | |||
< | </syntaxhighlight>الآن، قد ينجح طلب GET إلى /photos، ولكن سيخفق طلب POST إلى /photos (والذي عادةً ما يوجه إلى الإجراء <code>create</code>). | ||
الآن، قد ينجح طلب GET إلى /photos، ولكن سيخفق طلب POST إلى /photos (والذي عادةً ما يوجه إلى | |||
في هذه الحالة، ستنشئ | الخيار <code>:except</code> يحدد المسار أو قائمة المسارات التي لا يجب على ريلز أن تنشئها:<syntaxhighlight lang="rails"> | ||
resources :photos, except: :destroy | |||
</syntaxhighlight>في هذه الحالة، ستنشئ ريلز كل المسارات العادية باستثناء مسار التدمير (طلب DELETE إلى /photos/:id). | |||
فائدة: إذا كان التطبيق يحتوي على العديد من مسارات RESTful، فاستعمال :only و :except لتوليد مسارات التوجيه التي تحتاجها فعليًا فقط يمكن من تقليل استخدام الذاكرة وتسريع عملية التوجيه. | '''فائدة''': إذا كان التطبيق يحتوي على العديد من مسارات RESTful، فاستعمال <code>:only</code> و <code>:except</code> لتوليد مسارات التوجيه التي تحتاجها فعليًا فقط يمكن من تقليل استخدام الذاكرة وتسريع عملية التوجيه. | ||
=== المسارات المبدَّلة === | === المسارات المبدَّلة === | ||
باستخدام | باستخدام <code>scope</code>، يمكننا تغيير أسماء المسارات التي أنشئت بواسطة <code>resources</code>:<syntaxhighlight lang="rails"> | ||
scope(path_names: { new: 'neu', edit: 'bearbeiten' }) do | scope(path_names: { new: 'neu', edit: 'bearbeiten' }) do | ||
resources :categories, path: 'kategorien' | |||
end | end | ||
</syntaxhighlight>تنشئ ريلز الآن مسارات موجهة إلى <code>CategoriesContator</code>. | |||
تنشئ | |||
{| class="wikitable" | {| class="wikitable" | ||
!فعل HTTP | |||
!المسار | |||
!وحدة التحكم # الإجراء | |||
!مسمى المساعد | |||
|- | |- | ||
|GET | |GET | ||
|/kategorien | |/kategorien | ||
|categories#index | |<code>categories#index</code> | ||
|categories_path | |<code>categories_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/kategorien/neu | |/kategorien/neu | ||
|categories#new | |<code>categories#new</code> | ||
|new_category_path | |<code>new_category_path</code> | ||
|- | |- | ||
|POST | |POST | ||
|/kategorien | |/kategorien | ||
|categories#create | |<code>categories#create</code> | ||
|categories_path | |<code>categories_path</code> | ||
|- | |- | ||
|GET | |GET | ||
|/kategorien/:id | |/kategorien/:id | ||
|categories#show | |<code>categories#show</code> | ||
|category_path(:id) | |<code>category_path(:id)</code> | ||
|- | |- | ||
|GET | |GET | ||
|/kategorien/:id/bearbeiten | |/kategorien/:id/bearbeiten | ||
|categories#edit | |<code>categories#edit</code> | ||
|edit_category_path(:id) | |<code>edit_category_path(:id)</code> | ||
|- | |- | ||
|PATCH/PUT | |PATCH/PUT | ||
|/kategorien/:id | |/kategorien/:id | ||
|categories#update | |<code>categories#update</code> | ||
|category_path(:id) | |<code>category_path(:id)</code> | ||
|- | |- | ||
|DELETE | |DELETE | ||
|/kategorien/:id | |/kategorien/:id | ||
|categories#destroy | |<code>categories#destroy</code> | ||
|category_path(:id) | |<code>category_path(:id)</code> | ||
|} | |} | ||
=== استبدال النموذج المفرد === | === استبدال النموذج المفرد === | ||
إذا كنت تريد تعريف الشكل المفرد لمورد، فيجب عليك إضافة قواعد إضافية إلى Inflector: | إذا كنت تريد تعريف الشكل المفرد لمورد، فيجب عليك إضافة قواعد إضافية إلى <code>Inflector</code>:<syntaxhighlight lang="rails"> | ||
ActiveSupport::Inflector.inflections do |inflect| | ActiveSupport::Inflector.inflections do |inflect| | ||
inflect.irregular 'tooth', 'teeth' | |||
end | end | ||
</syntaxhighlight> | |||
=== استخدام :as في الموارد المتداخلة === | === استخدام <code>:as</code> في الموارد المتداخلة === | ||
الخيار :as يستبدل الاسم الذي أُنشِأ تلقائيًا للمورد في مساعدي المسارات الموجهة المتداخلة. فمثلًا: | الخيار <code>:as</code> يستبدل الاسم الذي أُنشِأ تلقائيًا للمورد في مساعدي المسارات الموجهة المتداخلة. فمثلًا:<syntaxhighlight lang="rails"> | ||
resources :magazines do | resources :magazines do | ||
resources :ads, as: 'periodical_ads' | |||
end | end | ||
</syntaxhighlight>سيؤدي ذلك إلى إنشاء مساعدين للتوجيه مثل <code>magazine_periodical_ads_url</code> و <code>edit_magazine_periodical_ad_path</code>. | |||
سيؤدي ذلك إلى إنشاء مساعدين للتوجيه مثل magazine_periodical_ads_url و edit_magazine_periodical_ad_path. | |||
=== استبدال معاملات المسار الموجه المسماة === | === استبدال معاملات المسار الموجه المسماة === | ||
يستبدل الخيار param: معرف المورد :id الافتراضي (اسم الجزء الديناميكي المستخدم لإنشاء المسارات الموجهة). يمكنك الوصول إلى هذا الجزء من وحدة التحكم باستخدام params[<:param>]. | يستبدل الخيار <code>param:</code> معرف المورد <code>:id</code> الافتراضي (اسم الجزء الديناميكي المستخدم لإنشاء المسارات الموجهة). يمكنك الوصول إلى هذا الجزء من وحدة التحكم باستخدام <code>params[<:param>]</code>.<syntaxhighlight lang="rails"> | ||
resources :videos, param: :identifier | resources :videos, param: :identifier | ||
</syntaxhighlight><syntaxhighlight lang="rails"> | |||
videos GET /videos(.:format) videos#index | |||
POST /videos(.:format) videos#create | |||
new_videos GET /videos/new(.:format) videos#new | |||
edit_videos GET /videos/:identifier/edit(.:format) videos#edit | |||
new_videos GET | </syntaxhighlight><syntaxhighlight lang="rails"> | ||
edit_videos GET | |||
Video.find_by(identifier: params[:identifier]) | Video.find_by(identifier: params[:identifier]) | ||
</syntaxhighlight>يمكنك استبدال <code>ActiveRecord::Base#to_param</code> لنموذج ذي صلة لإنشاء عنوان URL:<syntaxhighlight lang="rails"> | |||
يمكنك استبدال ActiveRecord::Base#to_param لنموذج ذي صلة لإنشاء عنوان URL: | |||
class Video < ApplicationRecord | class Video < ApplicationRecord | ||
def to_param | |||
identifier | |||
end | |||
end | end | ||
video = Video.find_by(identifier: "Roman-Holiday") | video = Video.find_by(identifier: "Roman-Holiday") | ||
edit_videos_path(video) # => "/videos/Roman-Holiday" | edit_videos_path(video) # => "/videos/Roman-Holiday" | ||
</syntaxhighlight> | |||
== فحص واختبار المسارات الموجهة == | == فحص واختبار المسارات الموجهة == | ||
توفر | توفر ريلز أدوات ووسائل لفحص واختبار المسارات الموجهة الخاصة بك. | ||
=== قائمة المسارات الحالية === | === قائمة المسارات الحالية === | ||
للحصول على قائمة كاملة بالمسارات المتاحة في التطبيق الخاص بك، قم بزيارة <nowiki>http://localhost:3000/rails/info/routes</nowiki> في المستعرض الخاص بك أثناء تشغيل خادمك في بيئة التطوير. يمكنك أيضًا تنفيذ الأمر rails routes في الطرفية الخاصة بك لإنتاج نفس المخرجات. | للحصول على قائمة كاملة بالمسارات المتاحة في التطبيق الخاص بك، قم بزيارة <nowiki>http://localhost:3000/rails/info/routes</nowiki> في المستعرض الخاص بك أثناء تشغيل خادمك في بيئة التطوير. يمكنك أيضًا تنفيذ الأمر <code>rails routes</code> في الطرفية الخاصة بك لإنتاج نفس المخرجات. | ||
ستقوم كلا الطريقتين بإدراج جميع مساراتك الموجهة بنفس الترتيب الذي تظهر به في config/routes.rb. لكل مسار، سترى: | ستقوم كلا الطريقتين بإدراج جميع مساراتك الموجهة بنفس الترتيب الذي تظهر به في config/routes.rb. لكل مسار، سترى: | ||
سطر 1٬370: | سطر 1٬025: | ||
* نمط عنوان URL المراد مطابقته. | * نمط عنوان URL المراد مطابقته. | ||
* معاملات التوجيه للمسار الموجه. | * معاملات التوجيه للمسار الموجه. | ||
على سبيل المثال، إليك مقطع صغير من مخرجات الأمر rails routes لمسار RESTful الموجه: | على سبيل المثال، إليك مقطع صغير من مخرجات الأمر <code>rails routes</code> لمسار RESTful الموجه:<syntaxhighlight lang="rails"> | ||
users GET /users(.:format) users#index | |||
POST /users(.:format) users#create | |||
new_user GET /users/new(.:format) users#new | |||
edit_user GET /users/:id/edit(.:format) users#edit | |||
</syntaxhighlight>يمكنك البحث من خلال مساراتك الموجهة باستخدام الخيار <code>grep: -g</code>. يظهر هذا الأمر أي مسارات موجهة تتطابق جزئيًا مع اسم تابع مساعد العنوان URL، أو فعل HTTP، أو مسار عنوان URL.<syntaxhighlight lang="shell"> | |||
new_user GET | |||
edit_user GET | |||
يمكنك البحث من خلال مساراتك الموجهة باستخدام الخيار | |||
$ bin/rails routes -g new_comment | $ bin/rails routes -g new_comment | ||
$ bin/rails routes -g POST | $ bin/rails routes -g POST | ||
$ bin/rails routes -g admin | $ bin/rails routes -g admin | ||
</syntaxhighlight>إذا كنت ترغب فقط في رؤية المسارات الموجهة التي تعين إلى وحدة تحكم معينة، فهناك الخيار <code>-c</code>:<syntaxhighlight lang="shell"> | |||
إذا كنت ترغب فقط في رؤية المسارات الموجهة التي تعين إلى وحدة تحكم معينة، فهناك الخيار -c: | |||
$ bin/rails routes -c users | $ bin/rails routes -c users | ||
$ bin/rails routes -c admin/users | $ bin/rails routes -c admin/users | ||
$ bin/rails routes -c Comments | $ bin/rails routes -c Comments | ||
$ bin/rails routes -c Articles::CommentsController | $ bin/rails routes -c Articles::CommentsController | ||
</syntaxhighlight>'''فائدة''': ستجد أن المخرجات من الأمر <code>rails routes</code> أكثر قابلية للقراءة إذا قمت بتوسيع نافذة طرفيتك حتى لا تلتف سطور المخرجات. | |||
فائدة: ستجد أن المخرجات من الأمر rails routes أكثر قابلية للقراءة إذا قمت بتوسيع نافذة طرفيتك حتى لا تلتف سطور المخرجات. | |||
=== اختبار المسارات الموجهة === | === اختبار المسارات الموجهة === | ||
يجب تضمين المسارات الموجهة في إستراتيجية الاختبار (تمامًا مثل بقية تطبيقك). تقدم | يجب تضمين المسارات الموجهة في إستراتيجية الاختبار (تمامًا مثل بقية تطبيقك). تقدم ريلز ثلاثة [https://api.rubyonrails.org/v5.2.2/classes/ActionDispatch/Assertions/RoutingAssertions.html تأكيدات مضمنة] مصممة لجعل عملية اختبار المسارات الموجهة أكثر بساطة: | ||
* Assert_generates | * <code>Assert_generates</code> | ||
* Assert_recognizes | * <code>Assert_recognizes</code> | ||
* assert_routing | * <code>assert_routing</code> | ||
==== تأكيد <code>assert_generates</code> ==== | |||
يؤكد <code>assert_generates</code> أن مجموعة معينة من الخيارات تولد مسارًا معينًا ويمكن استخدامها مع المسارات الافتراضية أو المسارات المخصصة. إليك المثال التالي:<syntaxhighlight lang="rails"> | |||
assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' } | assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' } | ||
assert_generates '/about', controller: 'pages', action: 'about' | assert_generates '/about', controller: 'pages', action: 'about' | ||
</syntaxhighlight> | |||
==== تأكيد assert_recognizes ==== | ==== تأكيد <code>assert_recognizes</code> ==== | ||
هو عكس التأكيد | هو عكس التأكيد <code>assert_generates</code>، إذ يؤكد أنه جرى التعرف على مسار معين ووُجِّه إلى مكان معين في التطبيق الخاص بك. إليك المثال التالي:<syntaxhighlight lang="rails"> | ||
assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1') | assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1') | ||
</syntaxhighlight>يمكنك توفير الوسيط <code>method:</code> لتحديد فعل HTTP:<syntaxhighlight lang="rails"> | |||
assert_recognizes({ controller: 'photos', action: 'create' }, { path: 'photos', method: :post }) | |||
</syntaxhighlight> | |||
==== تأكيد <code>assert_routing</code> ==== | |||
يتحقق تأكيد <code>assert_routing</code> من الطريقتين: يختبر أن المسار يولد الخيارات، وأن الخيارات تولد المسار. وبالتالي، فهو يجمع بين وظائف <code>assert_generates</code> و <code>assert_recognizes</code>:<syntaxhighlight lang="rails"> | |||
==== تأكيد assert_routing ==== | |||
يتحقق تأكيد assert_routing من الطريقتين: يختبر أن المسار يولد الخيارات، وأن الخيارات تولد المسار. وبالتالي، فهو يجمع بين وظائف assert_generates و assert_recognizes: | |||
assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' }) | assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' }) | ||
</syntaxhighlight> | |||
المصادر | == المصادر == | ||
* | * [https://guides.rubyonrails.org/routing.html صفحة Rails Routing from the Outside In في توثيق Ruby On Rails الرسمي.] |
المراجعة الحالية بتاريخ 10:20، 24 مارس 2019
يغطي هذا الدليل الميزات التي يواجهها المستخدم في عمليات التوجيه في ريلز.
بعد قراءة هذا الدليل، ستعرف:
- كيفية تفسير الشيفرة في config/routes.rb.
- كيفية بناء المسارات الخاصة بك باستخدام إما أسلوب الحيلة (resourceful style) المفضل أو طريقة المطابقة (match method).
- كيفية الإعلان عن معاملات المسار الموجه، والتي تمرر إلى إجراءات وحدة التحكم (controller actions).
- كيفية إنشاء المسارات وعناوين URL تلقائيًا باستخدام مساعدي المسار الموجه.
- التقنيات المتقدمة مثل إنشاء قيود وتثبيت نقاط نهاية Rack.
الغرض من توجيه المسارات في ريلز
يتعرف جهاز التوجيه في ريلز على عناوين URL ويرسلها إلى إجراء وحدة التحكم Action Controller، أو إلى تطبيق Rack. ويمكنه أيضًا إنشاء مسارات وعناوين URL، مع تجنب الحاجة إلى استخدام رموز ثابتة في الواجهة الخاصة بك.
توصيل عناوين URL بالشيفرة
عندما يتلقى تطبيق ريلز طلبًا واردًا مثل: GET /patients/17
يطلب من جهاز التوجيه مطابقته مع إجراء وحدة تحكم Action Controller. إذا كان أول مسار مطابق هو:
get '/patients/:id', to: 'patients#show'
يرسل الطلب إلى وحدة التحكم patients
الخاص بالإجراء show
مع { id: '17' }
في params
.
إنشاء مسارات وعناوين URL من الشيفرة
يمكنك أيضًا إنشاء مسارات وعناوين URL. إذا تم تعديل المسار الموجه أعلاه ليكون:
get '/patients/:id', to: 'patients#show', as: 'patient'
ويحتوي التطبيق الخاص بك على هذا الرمز في وحدة التحكم:
@patient = Patient.find(params[:id])
وهذا في الواجهة يقابل:
<%= link_to 'Patient Record', patient_path(@patient) %>
ثم ينشئ جهاز التوجيه المسار /patients/17. هذا يقلل من هشاشة الواجهة الخاص بك ويجعل التعليمات البرمجية الخاصة بك أسهل للفهم. لاحظ أن الهوية id
لا تحتاج إلى التحديد في مساعد المسار الموجه.
تهيئة جهاز توجيه المسارات في ريلز
توجد المسارات الموجهة للتطبيق أو المحرك (engine) في الملف config/routes.rb وعادةً ما تبدو كالتالي:
Rails.application.routes.draw do
resources :brands, only: [:index, :show] do
resources :products, only: [:index, :show]
end
resource :basket, only: [:show, :update, :destroy]
resolve("Basket") { route_for(:basket) }
end
نظرًا لأن هذا ملف مصدر روبي منتظم، يمكنك استخدام جميع ميزاته لمساعدتك في تحديد مساراتك الموجهة، لكن كن حذرًا مع أسماء المتغيرات، إذ إنها يمكن أن تتعارض مع توابع DSL الخاصة بالموجه.
ملاحظة: تقوم الكتلة Rails.application.routes.draw do… end
التي تلتزم بتعريفات المسار الموجه الخاصة بك بإنشاء النطاق الخاص بجهاز التوجيه DSL ويجب عدم حذفه.
توجيه المورد: الافتراضي في ريلز
يتيح لك توجيه الموارد إمكانية الإعلان بسرعة عن جميع المسارات الشائعة لوحدة التحكم كثيرة الموارد. بدلًا من الإعلان عن مسارات موجهة منفصلة للإجراءات index
، و show
، و new
، و edit
، و create
، و update
و destroy
الخاصة بك، فإن المسار كثير المورد يعلن عنه في سطر واحد من الشيفرة.
الموارد على الويب
تطلب صفحات المتصفحات من ريلز عن طريق تقديم طلب لعنوان URL باستخدام تابع HTTP محدد، مثل GET و POST و PATCH و PUT و DELETE. كل تابع هو طلب لتنفيذ عملية على المورد. يحدد مسار المورد الموجه عددًا من الطلبات ذات الصلة بالإجراءات في وحدة التحكم الواحدة.
عندما يتلقى تطبيق ريلز طلبًا واردًا لما يلي:
DELETE /photos/17
يطلب من جهاز التوجيه لتعيينه إلى إجراء وحدة تحكم Action Controller. إذا كان أول مسار مطابق هو:
resources :photos
سترسل ريلز ذلك الطلب للإجراء destroy
على وحدة التحكم photos
مع {id: '17'}
في params
.
CRUD والأفعال والإجراءات
في ريلز، يوفر المسار كثير المورد تخطيطًا بين أفعال HTTP وعناوين URL لإجراءات التحكم. من خلال الاتفاقية، كل إجراء يخطط أيضًا لعملية CRUD محددة في قاعدة البيانات. إدخال فردي في ملف التوجيه يكون مثل:
resources :photos
ينشئ سبعة مسارات مختلفة في التطبيق الخاص بك معيَّنةً جميعها إلى وحدة التحكم Photos
:
فعل HTTP | المسار | وحدة التحكم # الإجراء | الاستخدامات |
---|---|---|---|
GET | /photos | photos#index
|
عرض قائمة بجميع الصور. |
GET | /photos/new | photos#new
|
إرجاع نموذج HTML لإنشاء صورة جديدة. |
POST | /photos | photos#create
|
خلق صورة جديدة. |
GET | /photos/:id | photos#show
|
عرض صورة محددة. |
GET | /photos/:id/edit | photos#edit
|
إرجاع نموذج HTML لتحرير صورة. |
PATCH/PUT | /photos/:id | photos#update
|
تحديث صورة معينة. |
DELETE | /photos/:id | photos#destroy
|
حذف صورة معينة. |
ملاحظة: نظرًا لأن جهاز التوجيه يستخدم الفعل HTTP وعنوان URL لمطابقة الطلبات الواردة، فإن أربعة عناوين URL تتحول إلى سبعة إجراءات مختلفة.
ملاحظة: تُطابَق مسارات ريلز بالترتيب المحدد لها، لذلك إذا كانت لديك resources :photos
الموجودة أعلى get photos/poll
، فسيطابق مسار الإجراء show
السطر resources
قبل سطر get
. لحل هذه المشكلة، قم بتحريك سطر get
فوق سطر resources
بحيث يطابقه أولًا.
المسار ومساعد URL
سيؤدي إنشاء مسار موجه كثير المورد إلى كشف عدد من المساعدين إلى وحدات التحكم في تطبيقك. في حالة resources :photos
:
photos_path returns /photos
new_photo_path returns /photos/new
edit_photo_path(:id) returns /photos/:id/edit (for instance, edit_photo_path(10) returns /photos/10/edit)
photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10)
كل من هؤلاء المساعدين لديه مساعد _url
مقابل (مثل photos_url
) الذي يعيد نفس المسار مسبوقًا ببادئة المضيف والمنفذ والمسار الحالي.
تحديد موارد متعددة في نفس الوقت
إذا كنت بحاجة إلى إنشاء مسارات توجيه لأكثر من مورد واحد، فيمكنك توفير جزء من الكتابة عن طريق تعريفهم جميعًا باستدعاءٍ واحدٍ إلى resources
:
resources :photos, :books, :videos
هذا يعمل بالضبط بطريقة مشابهة للشيفرة التالية:
resources :photos
resources :books
resources :videos
الموارد الفردية
في بعض الأحيان، يكون لديك مورد يبحث عنه العملاء دائمًا دون الإشارة إلى معرف ID. على سبيل المثال، ترغب في أن يعرض /profile دائمًا ملف تعريف المستخدم الذي قام بتسجيل الدخول حاليًا. في هذه الحالة، يمكنك استخدام مورد مفرد لتعيين /profile (بدلًا من /profile/:id) إلى الإجراء show
:
get 'profile', to: 'users#show'
تمرير سلسلة نصية (String) إلى to:
ستتوقع أن تكون بالتنسيق controller#action
. عند استخدام رمز (Symbol)، يجب استبدال الخيار to:
بالقيمة action:
. عند استخدام سلسلة نصية دون الرمز #
، يجب استبدال الخيار to:
بـ controller:
بالشكل التالي:
get 'profile', action: :show, controller: 'users'
هذا مسار موجه كثير المورد:
resource :geocoder
resolve('Geocoder') { [:geocoder] }
يخلق ستة مسارات موجهة مختلفة في التطبيق الخاص بك كلها معيَّنة إلى وحدة التحكم Geocoders
:
فعل HTTP | المسار | وحدة التحكم # الإجراء | الإستخدامات |
---|---|---|---|
GET | /geocoder/new | geocoders#new
|
إرجاع نموذج HTML لإنشاء geocoder. |
POST | /geocoder | geocoders#create
|
إنشاء geocoder جديد. |
GET | /geocoder | geocoders#show
|
عرض مورد geocoder واحد و فقط. |
GET | /geocoder/edit | geocoders#edit
|
إرجاع نموذج HTML لتحرير geocoder. |
PATCH/PUT | /geocoder | geocoders#update
|
تحديث مورد geocoder واحد و فقط. |
DELETE | /geocoder | geocoders#destroy
|
حذف مورد geocoder. |
ملاحظة: نظرًا لأنك قد ترغب في استخدام وحدة التحكم نفسها لمسار فريد (/account) ومسار الجمع (/accounts/45)، فإن الموارد الفردية ستخضع إلى وحدات تحكم الجمع. على سبيل المثال، المورد :photo
والموارد :photos
تنشئ مسارات توجيه مفرد ومجتمعة تعين لنفس وحدة التحكم (PhotosController).
يولّد المسار الموجه كثير المورد المفرد (singular resourceful route) هؤلاء المساعدين:
new_geocoder_path returns /geocoder/new
edit_geocoder_path returns /geocoder/edit
geocoder_path returns /geocoder
كما هو الحال مع موارد الجمع، فإن نفس المساعدين الذين ينتهون في _url
سيتضمنون أيضًا بادئة المضيف والمنفذ والمسار.
وحدة تحكم مجالات الأسماء والتوجيه
قد ترغب في تنظيم مجموعات من وحدات التحكم تحت مجال اسم (namespace). الأكثر شيوعًا، يمكنك تجميع عدد من وحدات التحكم الإدارية تحت مجال الاسم Admin::
. يمكنك وضع وحدات التحكم هذه تحت دليل app/controllers/admin، ويمكنك تجميعها معًا في جهاز التوجيه:
namespace :admin do
resources :articles, :comments
end
سيؤدي ذلك إلى إنشاء عدد من المسارات لكل من وحدة التحكم في articles
و comments
. من أجل Admin::ArticlesController
، ستنشئ ريلز:
فعل HTTP | المسار | وحدة التحكم # الإجراء | مسمى المساعد |
---|---|---|---|
GET | /admin/articles | admin/articles#index
|
admin_articles_path
|
GET | /admin/articles/new | admin/articles#new
|
new_admin_article_path
|
POST | /admin/articles | admin/articles#create
|
admin_articles_path
|
GET | /admin/articles/:id | admin/articles#show
|
admin_article_path(:id)
|
GET | /admin/articles/:id/edit | admin/articles#edit
|
edit_admin_article_path(:id)
|
PATCH/PUT | /admin/articles/:id | admin/articles#update
|
admin_article_path(:id)
|
DELETE | /admin/articles/:id | admin/articles#destroy
|
admin_article_path(:id)
|
إذا كنت تريد توجيه /articles (بدون البادئة /admin) إلى Admin::ArticlesController
، فيمكنك استخدام:
scope module: 'admin' do
resources :articles, :comments
end
أو في حالة واحدة:
resources :articles, module: 'admin'
إذا كنت تريد توجيه /admin/articles إلى ArticlesController
(بدون بادئة الوحدة Admin::
)، فيمكنك استخدام:
scope '/admin' do
resources :articles, :comments
end
أو في حالة واحدة:
resources :articles, path: '/admin/articles'
في كل من هذه الحالات، تظل المسارات الموجهة المسماة كما هي إذا لم تستخدم النطاق (scope). في الحالة الأخيرة، تعيَّن المسارات التالية إلى ArticlesController
:
فعل HTTP | المسار | وحدة التحكم # الإجراء | مسمى المساعد |
---|---|---|---|
GET | /admin/articles | articles#index
|
articles_path
|
GET | /admin/articles/new | articles#new
|
new_article_path
|
POST | /admin/articles | articles#create
|
articles_path
|
GET | /admin/articles/:id | articles#show
|
article_path(:id)
|
GET | /admin/articles/:id/edit | articles#edit
|
edit_article_path(:id)
|
PATCH/PUT | /admin/articles/:id | articles#update
|
article_path(:id)
|
DELETE | /admin/articles/:id | articles#destroy
|
article_path(:id)
|
ملاحظة: إذا كنت بحاجة إلى استخدام مجال اسم وحدة تحكم (controller namespace) مختلف داخل كتلة مجال الاسم (namespace block)، فيمكنك تحديد مسار جهاز تحكم مطلق، مثل: get '/foo' => '/foo#index'
.
الموارد المتداخلة
من الشائع أن يكون لديك موارد منطقية للفرع childern من الموارد الأخرى. على سبيل المثال، لنفترض أن تطبيقك يتضمن هذه النماذج:
class Magazine < ApplicationRecord
has_many :ads
end
class Ad < ApplicationRecord
belongs_to :magazine
end
تتيح لك المسارات المتداخلة التقاط هذه العلاقة في التوجيه الخاص بك. في هذه الحالة، يمكنك تضمين إعلان المسار هذا:
resources :magazines do
resources :ads
end
بالإضافة إلى المسارات الموجهة للمجلات (magazines)، سيوجه هذا الإعلان أيضًا الإعلانات إلى AdsController
. تتطلب عناوين URL للإعلان عن مجلة:
فعل HTTP | المسار | وحدة التحكم # الإجراء | الاستخدامات |
---|---|---|---|
GET | /magazines/:magazine_id/ads | ads#index
|
عرض قائمة بجميع الإعلانات لمجلة محددة. |
GET | /magazines/:magazine_id/ads/new | ads#new
|
إرجاع نموذج HTML لإنشاء إعلان جديد ينتمي إلى مجلة معينة. |
POST | /magazines/:magazine_id/ads | ads#create
|
إنشاء إعلان جديد ينتمي إلى مجلة محددة. |
GET | /magazines/:magazine_id/ads/:id | ads#show
|
عرض إعلان معين ينتمي إلى مجلة محددة. |
GET | /magazines/:magazine_id/ads/:id/edit | ads#edit
|
إرجاع نموذج HTML لتحرير إعلان ينتمي إلى مجلة معينة. |
PATCH/PUT | /magazines/:magazine_id/ads/:id | ads#update
|
تحديث إعلان معين ينتمي إلى مجلة محددة. |
DELETE | /magazines/:magazine_id/ads/:id | ads#destroy
|
حذف إعلان معين ينتمي إلى مجلة محددة. |
سيؤدي هذا أيضًا إلى إنشاء مساعدين للتوجيه مثل magazine_ads_url
و edit_magazine_ad_path
. يأخذ هؤلاء المساعدون نسخة للمجلة كأول معامل (magazine_ads_url(@magazine))
.
حدود التداخل
يمكنك أن تشعِّب الموارد ضمن الموارد المتشعبة الأخرى إذا أردت ذلك. فمثلًا:
resources :publishers do
resources :magazines do
resources :photos
end
end
تصبح الموارد المتداخلة بعمق بطيئة. في هذه الحالة مثلًا، سيتعرف التطبيق على مسارات مثل:
/publishers/1/magazines/2/photos/3
سيكون مساعد المسار المقابل هو publisher_magazine_photo_url
، مما يتطلب منك تحديد كائنات على جميع المستويات الثلاثة. في الواقع، هذا الوضع مربكًا بما فيه الكفاية، إذ يقترح جيمس باك (Jamis Buck) في مقالة شائعة له قاعدةً أساسيةً لتصميم ريلز بشكل جيد: " لا ينبغي أبدًا أن تتداخل الموارد أكثر من 1 مستوى عميق."
التداخل الضحل
تتمثل إحدى طرق تجنب التداخل العميق (كما هو موصى به أعلاه) في إنشاء إجراءات المجموعة المحددة ضمن الأصل (parent)، وذلك للحصول على إحساس بالتسلسل الهرمي (hierarchy) ولعدم تداخل إجراءات العضو. بعبارة أخرى، لإنشاء مسارات فقط مع الحد الأدنى من المعلومات لتحديد المورد بشكل فريد، مثل هذا:
resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
تحقق هذه الفكرة توازنًا بين المسارات الوصفية والتداخل العميق. توجد صيغة مختصرة لتحقيق ذلك، عبر الخيار :shallow
:
resources :articles do
resources :comments, shallow: true
end
سيؤدي ذلك إلى إنشاء نفس المسارات بالضبط مثل المثال الأول. يمكنك أيضًا تحديد الخيار :shallow
في المورد الرئيسي parent
، وفي هذه الحالة ستكون جميع الموارد المتداخلة ضحلة:
resources :articles, shallow: true do
resources :comments
resources :quotes
resources :drafts
end
التابع الضحل shallow
الذي يخص DSL يخلق مجالًا داخليًا يكون كل تداخل فيه ضحلًا. هذا ينشئ نفس المسارات الموجهة مثل المثال السابق:
shallow do
resources :articles do
resources :comments
resources :quotes
resources :drafts
end
end
هناك خياران للنطاق (scope) لتخصيص المسارات الموجهة الضحلة. البادئات :shallow_path
لمسارات العضو مع المعامل المحدد:
scope shallow_path: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
يحتوي مورد التعليقات هنا على المسارات التالية التي أنشئت له:
فعل HTTP | المسار | وحدة التحكم# الإجراء | مسمى المساعد |
---|---|---|---|
GET | /articles/:article_id/comments(.:format) | comments#index
|
article_comments_path
|
POST | /articles/:article_id/comments(.:format) | comments#create
|
article_comments_path
|
GET | /articles/:article_id/comments/new(.:format) | comments#new
|
new_article_comment_path
|
GET | /sekret/comments/:id/edit(.:format) | comments#edit
|
edit_comment_path
|
GET | /sekret/comments/:id(.:format) | comments#show
|
comment_path
|
PATCH/PUT | /sekret/comments/:id(.:format) | comments#update
|
comment_path
|
DELETE | /sekret/comments/:id(.:format) | comments#destroy
|
comment_path
|
الخيار :shallow_prefix
يضيف المعامل المحدد للمساعدين المسمايين:
scope shallow_prefix: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
يحتوي مورد التعليقات هنا على المسارات الموجهة التالية التي أنشئت له:
فعل HTTP | المسار | وحدة التحكم# الإجراء | مسمى المساعد |
---|---|---|---|
GET | /articles/:article_id/comments(.:format) | comments#index
|
article_comments_path
|
POST | /articles/:article_id/comments(.:format) | comments#create
|
article_comments_path
|
GET | /articles/:article_id/comments/new(.:format) | comments#new
|
new_article_comment_path
|
GET | /comments/:id/edit(.:format) | comments#edit
|
edit_sekret_comment_path
|
GET | /comments/:id(.:format) | comments#show
|
sekret_comment_path
|
PATCH/PUT | /comments/:id(.:format) | comments#update
|
sekret_comment_path
|
DELETE | /comments/:id(.:format) | comments#destroy
|
sekret_comment_path
|
اهتمامات التوجيه
تسمح لك اهتمامات التوجيه (Routing concerns) بالإعلان عن المسارات الموجهة الشائعة التي يمكن إعادة استخدامها داخل الموارد والمسارات الأخرى. ألق نظرة على الشيفرة التالي لمعرفة كيفية تعريف اهتمام concern
:
concern :commentable do
resources :comments
end
concern :image_attachable do
resources :images, only: :index
end
يمكن استخدام هذه الاهتمامات concern
في الموارد لتجنب تكرار الرموز ومشاركة السلوك عبر المسارات:
resources :messages, concerns: :commentable
resources :articles, concerns: [:commentable, :image_attachable]
ما ورد أعلاه يعادل ما يلي:
resources :messages do
resources :comments
end
resources :articles do
resources :comments
resources :images, only: :index
end
كما يمكنك استخدامها في أي مكان تريده داخل المسارات الموجهة، مثل في استدعاء نطاق (scope) أو مجال أسماء (namespace):
namespace :articles do
concerns :commentable
end
إنشاء مسارات وعناوين URL من الكائنات
بالإضافة إلى استخدام مساعدين التوجيه، تستطيع Rails أيضًا إنشاء مسارات وعناوين URL من مصفوفة من المعاملات. على سبيل المثال، لنفترض أن لديك مجموعة المسارات الموجهة التالية:
resources :magazines do
resources :ads
end
عند استخدام magazine_ad_path
، يمكنك تمرير نسخ من Magazine
و Ad
بدلًا من المعرفات الرقمية IDs
:
<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>
يمكنك أيضًا استخدام url_for
مع مجموعة من الكائنات، وسوف تحدد ريلز المسار الموجهة الذي تريده تلقائيًا:
<%= link_to 'Ad details', url_for([@magazine, @ad]) %>
في هذه الحالة، سترى ريلز أن magazine@
هو Magazine
و ad@
هو Ad
وبالتالي ستستخدم المساعد magazine_ad_path
. في المساعدين مثل link_to
، يمكنك تحديد الكائن بدلًا من استدعاء url_for
بالكامل:
<%= link_to 'Ad details', [@magazine, @ad] %>
إذا كنت تريد الارتباط بمجلة فقط:
<%= link_to 'Magazine details', @magazine %>
بالنسبة إلى الإجراءات الأخرى، تحتاج فقط إلى إدراج اسم الإجراء باعتباره العنصر الأول في المصفوفة:
<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>
يتيح لك ذلك التعامل مع نسخ النماذج الخاصة بك كعناوين URL، وهي ميزة أساسية لاستخدام النمط كثير المورد.
إضافة المزيد من الإجراءات RESTful
لا تقتصر على المسارات الموجهة السبعة التي ينشئها توجيه RESTful بشكل افتراضي. يمكنك إضافة مسارات موجهة إضافية، إذا كنت ترغب في ذلك، تنطبق على المجموعة أو على أعضاء فرديين في المجموعة.
إضافة مسارات الأعضاء
لإضافة مسار موجه عضو، ما عليك سوى إضافة الكتلة member
إلى كتلة الموارد resource
:
resources :photos do
member do
get 'preview'
end
end
سيتعرف هذا على /photos/1/preview مع GET، ويوجهه إلى الإجراء preview
الذي يخص PhotosController
، مع تمرير قيمة معرف المورد id
في المعاملات [:id]
. سيؤدي أيضًا إلى إنشاء photos_preview_url
والمساعدين photo_preview_path
.
ضمن كتلة مسارات الأعضاء الموجهة، كل اسم مسار (route name) يحدد فعل HTTP سيُتعرَّف عليه. يمكنك استخدام get أو patch أو put أو post أو delete هنا. إذا لم يكن لديك العديد من مسارات الأعضاء الموجهة، فيمكنك أيضًا تمرير :on
إلى المسار، وإلغاء الكتلة:
resources :photos do
get 'preview', on: :member
end
يمكنك ترك الخيار :on
، إذ سيؤدي ذلك إلى إنشاء نفس مسار العضو باستثناء أن قيمة معرف المورد id
ستكون متاحة في [params[:photo_id
بدلًا من [params[:id
.
إضافة مسارات التجميع
لإضافة مسار موجه إلى المجموعة:
resources :photos do
collection do
get 'search'
end
end
سيؤدي هذا إلى تمكين ريلز للتعرف على مسارات مثل /photos/search باستخدام GET، والتوجيه إلى الإجراء search
الذي يخص PhotosController
. سيؤدي أيضًا إلى إنشاء مساعدي التوجيه search_photos_url
و search_photos_path
.
كما هو الحال مع توجيهات الأعضاء (member routes)، يمكنك تمرير :on
إلى توجيه بالشكل التالي:
resources :photos do
get 'search', on: :collection
end
إضافة توجيهات لإجراءات جديدة إضافية
يمكن إضافة إجراء جديد بديل باستخدام الاختصار :on بالشكل التالي:
resources :comments do
get 'preview', on: :new
end
سيؤدي هذا إلى تمكين ريلز للتعرف على مسارات مثل /comments/new/preview باستخدام GET، وتوجيهها إلى الإجراء preview
الذي يخص CommentController
. سيؤدي أيضًا إلى إنشاء مساعدي التوجيه preview_new_comment_url
و preview_new_comment_path
.
فائدة: إذا وجدت نفسك تضيف العديد من الإجراءات الإضافية إلى مسار موجه ذي أهمية، فقد حان الوقت للتوقف وسؤال نفسك ما إذا كنت تموه عن وجود مورد آخر.
المسارات الموجهة غير كثيرة المورد (Non-Resourceful)
بالإضافة إلى توجيه الموارد، تتمتع ريلز بدعم قوي لتوجيه عناوين URL العشوائية إلى الإجراءات. هنا، لا يمكنك الحصول على مجموعات من التوجيهات التي تنشأ تلقائيًا من خلال توجيه الموارد. بدلاً من ذلك، يمكنك إعداد كل توجيه على حدة داخل تطبيقك.
على الرغم من أنه يجب عليك عادة استخدام التوجيه كثير المورد (resourceful routing)، إلا أنه لا يزال هناك العديد من الأماكن التي يكون فيها التوجيه الأبسط أكثر ملاءمة. ليس هناك حاجة لمحاولة ارتداء كل جزء أخير من تطبيقك في إطار كثير المورد إذا لم يكن ذلك مناسبًا.
على وجه الخصوص، يجعل التوجيه البسيط من السهل جدًا تعيين عناوين URL القديمة لإجراءات ريلز الجديدة.
المعاملات المقيدة
عند إعداد مسار عادي، فإنك تقدم سلسلة من الرموز التي تحددها ريلز إلى أجزاء من طلب HTTP الوارد. على سبيل المثال، ضع في اعتبارك هذا المسار الموجه:
get 'photos(/:id)', to: :display
إذا تمت معالجة طلب وارد من /photos/1 من خلال هذا التوجيه (لأنه لم يطابق أي توجيه سابق في الملف)، فستكون النتيجة استدعاء الإجراء display
الذي يخص PhotosController
، ولجعل المعامل النهائي "1"متاحًا بالشكل [params[:id
. سيقوم هذا التوجيه أيضًا بتوجيه الطلب الوارد /photos إلى DisplayController#display
، نظرًا لأن المُعرِّف :id
هو مُعامل اختياري، يشار إليه بواسطة الأقواس.
الأجزاء الديناميكية
يمكنك إعداد العديد من الأجزاء الديناميكية (Dynamic Segments) ضمن مسار موجه عادي حسب رغبتك. سيكون أي جزء متاحًا للعمل كجزء من params
. إذا أعددت المسار الموجه التالي:
get 'photos/:id/:user_id', to: 'photos#show'
سيرسل المسار الوارد /photos/1/2 إلى الإجراء show
الخاص بـ [PhotosController.params [:id
. سيكون params[:id]
هو "1"، وسيكون [params[:user_id
هو "2".
فائدة: بشكل افتراضي، لا تقبل الأجزاء الديناميكية النقاط، وهذا يرجع إلى استخدام النقطة كفاصل للمسارات الموجهة المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل جزء ديناميكي، أضف قيدًا يتجاوز هذا مثل id: /[^\/]+/
الذي يسمح بأي شيء باستثناء الخط المستقيم المائل.
الأجزاء الثابتة
يمكنك تحديد الأجزاء الثابتة (Static Segments) عند إنشاء مسار موجه من خلال عدم إلحاق النقطتين بالجزء fragment:
get 'photos/:id/with_user/:user_id', to: 'photos#show'
يستجيب هذا المسار الموجه لمسارات مثل /photos/1/with_user/2. في هذه الحالة، ستكون
المعاملات هي {controller: 'photos'، action: 'show'، id: '1'، user_id: '2ٌ'}
.
سلسلة الاستعلام
ستشمل المعاملات أيضًا أي معاملات من سلسلة الاستعلام. على سبيل المثال، مع هذا المسار الموجه:
get 'photos/:id', to: 'photos#show'
سيرسل المسار الوارد /photos/1?user_id=2 إلى الإجراء show
الخاص بوحدة تحكم Photos
. إن params
ستكون { controller: 'photos', action: 'show', id: '1', user_id: '2' }
.
تحديد الافتراضات
يمكنك تحديد الإعدادات الافتراضية في المسار من خلال توفير تجزئة (hash) للخيار :defaults
. وينطبق هذا حتى على المعاملات التي لا تحددها كشرائح ديناميكية. فمثلًا:
get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' }
تطابق ريلز المسار photos/12 مع الإجراء show
الذي يخص showController
، وتعين params[:format]
إلى "jpg".
يمكنك أيضًا استخدام defaults
في تنسيق الكتلة لتحديد الإعدادات الافتراضية لعناصر متعددة:
defaults format: :json do
resources :photos
end
ملاحظة: لا يمكنك إلغاء القيم الافتراضية عبر معاملات الاستعلام وهذا يعود لأسباب أمنية. القيم الافتراضية الوحيدة التي يمكن تجاوزها هي الأجزاء الديناميكية عن طريق استبدالها في مسار URL.
تسمية المسارات الموجهة
يمكنك تحديد اسم لأي مسار موجه باستخدام الخيار :as:
get 'exit', to: 'sessions#destroy', as: :logout
سيؤدي ذلك إلى إنشاء logout_path
و logout_url
كمساعدين مسميين في تطبيقك. وسيؤدي استدعاء loging_path
إلى إعادة /exit.
يمكنك أيضًا استخدام هذا لتجاوز توابع التوجيه المحددة بواسطة الموارد كما يلي:
get ':username', to: 'users#show', as: :user
سيحدد هذا التابع user_path
الذي سيتاح في وحدات التحكم، والمساعدين والواجهات التي ستنتقل إلى مسار مثل /bob. داخل الخيار show
الخاص بـ UsersController
، تحتوي [params[:username
على اسم المستخدم للمستخدم. غير :username
في تعريف المسار الموجه إذا كنت لا تريد أن يكون اسم المعامل :username
.
قيود فعل HTTP
بشكل عام، يجب عليك استخدام التوابع get و post و put و patch و delete لتقييد توجيه إلى فعل معين. يمكنك استخدام التابع match
مع الخيار :via
لمطابقة أفعال متعددة في وقت واحد:
match 'photos', to: 'photos#show', via: [:get, :post]
يمكنك مطابقة جميع الأفعال إلى مسار معين باستخدام via: :all
كما يلي:
match 'photos', to: 'photos#show', via: :all
ملاحظة: توجيه كل من طلبيات GET و POST إلى إجراء واحد له آثار متعلقة بالأمان. بشكل عام، يجب تجنب توجيه جميع الأفعال إلى أي إجراء ما لم يكن لديك سبب وجيه لذلك.
ملاحظة: لن تتحقق طلبية GET في ريلز من رمز CSRF (اختصار للعبارة cross-site request forgery، وهي الهجمات مُزوّرة الطلب عبر المواقع). يجب ألا تكتب أبدًا إلى قاعدة البيانات من طلبيات GET؛ لمزيد من المعلومات، انظر دليل الأمان الخاص بإجراءات CSRF المضادة.
قيود الجزء (Segment Constraints)
يمكنك استخدام الخيار :constraints
لفرض تنسيق لجزء ديناميكي بالشكل التالي:
get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }
يطابق هذا المسار الموجه مسارات مثل /photos/A12345، ولكن ليس /photos/893. يمكنك التعبير بشكل أكثر دقة عن نفس التوجيه بهذه الطريقة:
get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/
تأخذ :constraints
تعبيرات نمطية مع القيود التي لا يمكن أن تستخدم مثبتات التعبير النمطي (regexp anchors). على سبيل المثال، لن يعمل التوجيه التالي:
get '/:id', to: 'articles#show', constraints: { id: /^\d/ }
ومع ذلك، لاحظ أنك لست بحاجة إلى استخدام نقاط تثبيت لأن جميع المسارات الموجهة المثبتة في البداية.
على سبيل المثال، تسمح التوجيهات التالية لـ articles
التي لها قيم to_param
مثل 1-hello-world
والتي تبدأ دائمًا برقم ولـ users
التي لها قيم to_param
مثل david
التي لا تبدأ برقم بمشاركة مجال الاسم الجذر (root namespace):
get '/:id', to: 'articles#show', constraints: { id: /\d.+/ }
get '/:username', to: 'users#show'
قيود على أساس الطلب
يمكنك أيضًا تقييد مسار موجه استنادًا إلى أي تابع في كائن الطلب Request
التي يعيد سلسلة نصية.
يمكنك تحديد القيد على أساس الطلب بنفس الطريقة التي تحدد بها قيد الجزء (segment constraint):
get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' }
يمكنك أيضًا تحديد القيود في نموذج الكتلة:
namespace :admin do
constraints subdomain: 'admin' do
resources :photos
end
end
ملاحظة: تعمل قيود الطلب عن طريق استدعاء تابع في كائن الطلب Request
يحمل نفس الاسم مثل مفتاح التجزئة (hash) ثم مقارنة القيمة المعادة بقيمة الجدول Hash. لذلك، يجب أن تتطابق قيم القيد مع نوع إرجاع تابع كائن الطلب المقابل. على سبيل المثال: { 'constraints: { subdomain: 'api
سيطابق نطاقًا فرعيًا لواجهة برمجة التطبيق كما هو متوقع، ولكن لن يكون باستخدام رمز مثل
{ constraints: { subdomain: :api
، نظرًا لأن request.subdomain
يعرض "api"
كسلسلة نصية.
ملاحظة: هناك استثناء للقيد format
وهو في حين أنه تابع في كائن الطلب Request
، وهو أيضًا معامل اختياري ضمني في كل مسار. يكون لقيود الشريحة الأسبقية وتطبق قيود التنسيق فقط عند فرضها عبر التجزئة. على سبيل المثال، get 'foo', constraints: { format: 'json' }
سيطابق GET /foo
لأن التنسيق اختياري بشكل افتراضي. ومع ذلك، يمكنك استخدام تعابير lambda مثل { get 'foo', constraints: lambda { |req| req.format == :json
وسيتطابق مسار التوجيه مع طلبيات JSON الصريحة فقط.
القيود المتقدمة
إذا كان لديك قيد أكثر تقدمًا، يمكنك توفير كائن يستجيب إلى matches?
التي يجب أن تستخدمها ريلز. لنفترض أنك تريد توجيه جميع المستخدمين في القائمة السوداء إلى BlacklistController
، يمكنك القيام بذلك بالشكل التالي:
class BlacklistConstraint
def initialize
@ips = Blacklist.retrieve_ips
end
def matches?(request)
@ips.include?(request.remote_ip)
end
end
Rails.application.routes.draw do
get '*path', to: 'blacklist#index',
constraints: BlacklistConstraint.new
end
يمكنك أيضا تحديد القيود على أنها تعابير lambda:
Rails.application.routes.draw do
get '*path', to: 'blacklist#index',
constraints: lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) }
end
كل من التابع matches?
وتعابير lambda تحصل على كائن الطلب Request
كوسيط.
التوجيه النمطي والأجزاء المتطابقة بالمحارف الخاصة
التوجيه النمطي (Route globbing) هو طريقة لتحديد أنه يجب مطابقة معامل معين مع جميع الأجزاء المتبقية من المسار. فمثلًا:
get 'photos/*other', to: 'photos#unknown'
سيطابق هذا التوجيه المسار photos/12 أو /photos/long/path/to/12 مع تعيين [params[:other
إلى "12" أو "long/path/to/12". تسمى الأجزاء المسبوقة بالرمز *
باسم "الأجزاء المتطابقة بالمحارف الخاصة" (wildcard segments).
يمكن أن تظهر الأجزاء المتطابقة بالمحارف الخاصة في أي مكان في المسار. فمثلًا:
get 'books/*section/:title', to: 'books#show'
من شأنه أن يطابق books/some/section/last-words-a-memoir مع [params[:section
الذي يساوي 'some/section'، ومع [params [:title
الذي يساوي 'last-words-a-memoir'.
من الناحية الفنية، يمكن أن يحتوي المسار على أكثر من جزء واحدة متطابق. يعين المطابق (matcher) الأجزاء إلى معاملات بطريقة بديهية. فمثلًا:
get '*a/foo/*b', to: 'test#index'
سيطابق zoo/woo/foo/bar/baz مع [params[:a
الذي يساوي 'zoo/woo'، ومع [params[:b
الذي يساوي 'bar/baz'.
ملاحظة: عبر طلب '/foo/bar.json'، ستكون [params[:pages
مساوية لـ '/foo/bar' مع تنسيق طلب JSON. إذا كنت تريد استعادة سلوك الإصدار 3.0.x القديم، فيمكنك توفير format: false
بالشكل التالي:
get '*pages', to: 'pages#show', format: false
إذا كنت تريد جعل جزء التنسيق إلزاميًا، وبذلك لا يمكن حذفه، فيمكنك توفير format: true
بالشكل التالي:
get '*pages', to: 'pages#show', format: true
إعادة التوجيه
يمكنك إعادة توجيه (redirect) أي مسار إلى مسار آخر باستخدام مساعد إعادة التوجيه redirect
في المسار الموجه الخاص بك:
get '/stories', to: redirect('/articles')
يمكنك أيضًا إعادة استخدام أجزاء ديناميكية من المطابقة في المسار لإعادة التوجيه إلى:
get '/stories/:name', to: redirect('/articles/%{name}')
يمكنك أيضًا توفير حظر لإعادة التوجيه، والذي يتلقى معاملات المسار الرمزية وكائن الطلب Request
:
get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" }
get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" }
يرجى ملاحظة أن إعادة التوجيه الافتراضية هي عملية إعادة توجيه 301 "تم نقلها بشكل دائم" (Moved Permanently). ضع في اعتبارك أن بعض متصفحات الويب أو الخوادم الوسيطة (proxy servers) ستخزن هذا النوع من إعادة التوجيه، مما يجعل الصفحة القديمة غير قابلة للوصول. يمكنك استخدام الخيار :status
لتغيير حالة الاستجابة:
get '/stories/:name', to: redirect('/articles/%{name}', status: 302)
في جميع هذه الحالات، إذا لم تقدم المضيف الأساسي (http://www.example.com)، فستأخذ ريلز هذه التفاصيل من الطلب الحالي.
التوجيه إلى تطبيقات Rack
بدلاً من سلسلة نصية مثل 'articles#index'
، والتي تتطابق مع الإجراء index
في ArticlesController
، يمكنك تحديد أي تطبيق Rack كنقطة نهاية للمطابق:
match '/application.js', to: MyRackApp, via: :all
طالما يستجيب MyRackApp
لاستدعاء ويعيد [status, headers, body]
، لن يعرف جهاز التوجيه الفرق بين تطبيق Rack والإجراء. هذا هو الاستخدام المناسب لـ via: :all
، كما تريد السماح لتطبيق Rack الخاص بك بالتعامل مع جميع الأفعال التي تراها مناسبة.
ملاحظة: يوسع 'articles#index'
فعليًا إلى (ArticlesController.action(:index
، التي تُرجع تطبيق Rack صالحًا.
إذا قمت بتحديد تطبيق Rack كنقطة نهاية للمطابقة، فتذكر أنَّ التوجيه لن يتغير في تطبيق الاستلام. مع التوجيه التالي، يجب أن يتوقع تطبيق Rack أن يكون المسار هو /admin:
match '/admin', to: AdminApp, via: :all
إذا كنت تفضل أن يتلقى تطبيق Rack طلبات على المسار الجذر بدلًا من ذلك، فاستخدم mount
:
mount AdminApp, at: '/admin'
استخدام الجذر
يمكنك تحديد ما يجب أن تسلكه Rails عند توجيه '/' باستخدام التابع root
:
root to: 'pages#main'
root 'pages#main' # shortcut for the abov
يجب وضع مسار الجذر أعلى الملف، لأنه المسار الأكثر شيوعًا ويجب مطابقته أولاً.
ملاحظة: يوجه مسار الجذر فقط طلبيات GET إلى الإجراء.
يمكنك أيضًا استخدام الجذر داخل مجالات الأسماء والنطاقات أيضًا. فمثلًا:
namespace :admin do
root to: "admin#index"
end
root to: "home#index"
توجيهات محارف يونيكود
يمكنك تحديد توجيهات محارف يونيكود مباشرةً. فمثلًا:
get 'こんにちは', to: 'welcome#index'
التوجيهات المباشرة
يمكنك إنشاء مساعدين مخصصين لعناوين URL مباشرةً. فمثلًا:
direct :homepage do
"http://www.rubyonrails.org"
end
# >> homepage_url
# => "http://www.rubyonrails.org"
يجب أن تعيد الكتلة وسيطًا صالحًا للتابع url_for
. لذلك، يمكنك تمرير سلسلة URL صحيحة، أو جدول Hash، أو مصفوفة، أو نسخة من Active Model، أو صنف من Active Model:
direct :commentable do |model|
[ model, anchor: model.dom_id ]
end
direct :main do
{ controller: 'pages', action: 'index', subdomain: 'www' }
end
استخدام resolve
يسمح التابع resolve
بتخصيص تعيينات متعددة الأشكال (polymorphic mapping) للنماذج. فمثلًا:
resource :basket
resolve("Basket") { [:basket] }
<%= form_for @basket do |form| %>
<!-- basket form -->
<% end %>
سيؤدي ذلك إلى إنشاء عنوان URL هو /basket بدلًا من العنوان /baskets/:id المعتاد.
تخصيص التوجيهات كثيرة الموارد
في حين أن التوجيهات والمساعدات الافتراضية التي أنشئت بواسطة resources :articles
عادةً ما تخدمك جيدًا، فقد تحتاج إلى تخصيصها بطريقة ما. تسمح لك ريلز بتخصيص أي جزء عام من المساعدين كثيري الموارد (resourceful helpers).
تحديد وحدة تحكم لاستخدامها
يتيح لك الخيار :controller
تحديد وحدة تحكم بشكل صريح لاستخدامها في المورد. فمثلًا:
resources :photos, controller: 'images'
سيتعرف على المسارات الواردة التي تبدأ بـ /photos ولكن سيوجه إلى وحدة التحكم في Images
:
فعل HTTP | المسار | وحدة التحكم#الإجراء | مسمى المساعد |
---|---|---|---|
GET | /photos | images#index
|
photos_path
|
GET | /photos/new | images#new
|
new_photo_path
|
POST | /photos | images#create
|
photos_path
|
GET | /photos/:id | images#show
|
photo_path(:id)
|
GET | /photos/:id/edit | images#edit
|
edit_photo_path(:id)
|
PATCH/PUT | /photos/:id | images#update
|
photo_path(:id)
|
DELETE | /photos/:id | images#destroy
|
photo_path(:id)
|
ملاحظة: استخدم photos_photo
و new_photo_path
وما إلى ذلك لإنشاء مسارات لهذا المورد.
بالنسبة لوحدات تحكم ذات مجال أسماء (namespaced controllers)، يمكنك استخدام تدوين المجلد (directory notation). فمثلًا:
resources :user_permissions, controller: 'admin/user_permissions'
هذا سوف يوجهه إلى وحدة التحكم Admin::UserPermissions
.
ملاحظة: تدوين المجلد مدعومٌ فقط. يمكن أن يؤدي تحديد وحدة التحكم بتدوين روبي الثابت
(مثل controller: 'Admin::UserPermissions'
) إلى مشاكل في التوجيه ينتج عنها تحذيرات.
تحديد القيود
يمكنك استخدام الخيار :constraints
لتحديد التنسيق المطلوب على المعرّف id
الضمني. فمثلًا:
resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }
يقيد هذا الاعلان المعامل id:
ليطابق التعبير المعتاد الموفر. لذلك، في هذه الحالة، لم يعد جهاز التوجيه يتطابق مع /photos/1 مع هذا المسار. بدلًا من ذلك، إنَّ /photos/RR27 هي من ستتطابق.
يمكنك تحديد قيد واحد لتطبيقه على عدد من المسارات باستخدام نموذج الكتلة:
constraints(id: /[A-Z][A-Z][0-9]+/) do
resources :photos
resources :accounts
end
ملاحظة: بالطبع، يمكنك استخدام القيود الأكثر تقدمًا المتوفرة في المسارات غير كثيرة الموارد في هذا السياق.
فائدة: بشكل افتراضي، لا يقبل المعامل :id
النقاط وذلك لأن النقطة تستخدم كفاصل للمسارات المنسقة. إذا كنت بحاجة إلى استخدام نقطة داخل :id
، فأدخل قيدًا يتجاوز هذا مثل id: /[^\/]+/
يسمح بأي شيء باستثناء الشرطة المائلة.
تجاوز المساعدين المسماة
يسمح لك الخيار :as
بتجاوز التسمية العادية لمساعدي مسار معين. فمثلًا:
resources :photos, as: 'images'
سوف يتعرف على المسارات الواردة التي تبدأ بـ /photos ويوجه الطلبات إلى PhotosController
، ولكن استخدم الخيار :as
لتسمية المساعدين.
فعل HTTP | المسار | وحدة التحكم # الإجراء | مسمى المساعد |
---|---|---|---|
GET | /photos | photos#index
|
images_path
|
GET | /photos/new | photos#new
|
new_image_path
|
POST | /photos | photos#create
|
images_path
|
GET | /photos/:id | photos#show
|
image_path(:id)
|
GET | /photos/:id/edit | photos#edit
|
edit_image_path(:id)
|
PATCH/PUT | /photos/:id | photos#update
|
image_path(:id)
|
DELETE | /photos/:id | photos#destroy
|
image_path(:id)
|
استبدال الأجزاء الجديدة وتعديلها
يتيح لك الخيار :path_names
استبدال الأجزاء الجديدة وتعديلها تلقائيًا في المسارات:
resources :photos, path_names: { new: 'make', edit: 'change' }
قد يتسبب هذا في التعرف على المسارات مثل:
/photos/make
/photos/1/change
ملاحظة: لا تتغيير أسماء الإجراءات الفعلية بواسطة هذا الخيار. سيستمر المساران المعروضان في مسار التوجيه إلى الإجراءات الجديدة وتعديلها. فائدة: إذا وجدت نفسك ترغب في تغيير هذا الخيار بشكل موحد لجميع مسارات التوجيه لديك، فيمكنك استخدام النطاق.
scope path_names: { new: 'make' } do
# rest of your routes
end
إضافة بادئة لمساعدي مسار التوجيه المسمى
يمكنك استخدام الخيار :as
لإضافة بادئة لمساعدي مسار التوجيه المسمى الذي تُنشئُه ريلز لمسار التوجيه. استخدم هذا الخيار لمنع تضارب الأسماء بين المسارات باستخدام نطاق مسار. فمثلًا:
scope 'admin' do
resources :photos, as: 'admin_photos'
end
resources :photos
سيوفر ذلك مساعدين لمسارات التوجيه، مثل admin_photos_path
و new_admin_photo_path
وما إلى ذلك.
لإضافة بادئة لمجموعة من مساعدي مسارات التوجيه، استخدم الخيار :as
مع النطاق:
scope 'admin', as: 'admin' do
resources :photos, :accounts
end
resources :photos, :accounts
سيؤدي ذلك إلى إنشاء مسارات مثل admin_photos_path
و admin_accounts_path
والتي تعين /admin /photos و /admin/accounts على التوالي.
ملاحظة: سيضيف نطاق مجال الأسماء تلقائيًا الخيار :as
بالإضافة إلى البادئات :module
و :path
.
يمكن إضافة بادئة لمسارات التوجيه مع معامل مسمى أيضًا:
scope ':username' do
resources :articles
end
سيزودك هذا بعناوين URL مثل /bob/articles/1 وسيسمح لك بمراجعة الجزء username
من المسار
بالشكل [params[:username
في وحدات التحكم والمساعدين والواجهات.
تقييد مسارات التوجيه التي أنشئت
بشكل افتراضي، تنشئ ريلز مسارات توجيه للإجراءات الافتراضية السبعة (index
، و show
، و new
، و create
، و edit
، و update
، و destroy
) لكل مسار RESTful في التطبيق الخاص بك. يمكنك استخدام الخيارات :only
و :except
لضبط هذا السلوك. الخيار :only
يخبر ريلز بإنشاء المسارات المحددة فقط:
resources :photos, only: [:index, :show]
الآن، قد ينجح طلب GET إلى /photos، ولكن سيخفق طلب POST إلى /photos (والذي عادةً ما يوجه إلى الإجراء create
).
الخيار :except
يحدد المسار أو قائمة المسارات التي لا يجب على ريلز أن تنشئها:
resources :photos, except: :destroy
في هذه الحالة، ستنشئ ريلز كل المسارات العادية باستثناء مسار التدمير (طلب DELETE إلى /photos/:id).
فائدة: إذا كان التطبيق يحتوي على العديد من مسارات RESTful، فاستعمال :only
و :except
لتوليد مسارات التوجيه التي تحتاجها فعليًا فقط يمكن من تقليل استخدام الذاكرة وتسريع عملية التوجيه.
المسارات المبدَّلة
باستخدام scope
، يمكننا تغيير أسماء المسارات التي أنشئت بواسطة resources
:
scope(path_names: { new: 'neu', edit: 'bearbeiten' }) do
resources :categories, path: 'kategorien'
end
تنشئ ريلز الآن مسارات موجهة إلى CategoriesContator
.
فعل HTTP | المسار | وحدة التحكم # الإجراء | مسمى المساعد |
---|---|---|---|
GET | /kategorien | categories#index
|
categories_path
|
GET | /kategorien/neu | categories#new
|
new_category_path
|
POST | /kategorien | categories#create
|
categories_path
|
GET | /kategorien/:id | categories#show
|
category_path(:id)
|
GET | /kategorien/:id/bearbeiten | categories#edit
|
edit_category_path(:id)
|
PATCH/PUT | /kategorien/:id | categories#update
|
category_path(:id)
|
DELETE | /kategorien/:id | categories#destroy
|
category_path(:id)
|
استبدال النموذج المفرد
إذا كنت تريد تعريف الشكل المفرد لمورد، فيجب عليك إضافة قواعد إضافية إلى Inflector
:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'tooth', 'teeth'
end
استخدام :as
في الموارد المتداخلة
الخيار :as
يستبدل الاسم الذي أُنشِأ تلقائيًا للمورد في مساعدي المسارات الموجهة المتداخلة. فمثلًا:
resources :magazines do
resources :ads, as: 'periodical_ads'
end
سيؤدي ذلك إلى إنشاء مساعدين للتوجيه مثل magazine_periodical_ads_url
و edit_magazine_periodical_ad_path
.
استبدال معاملات المسار الموجه المسماة
يستبدل الخيار param:
معرف المورد :id
الافتراضي (اسم الجزء الديناميكي المستخدم لإنشاء المسارات الموجهة). يمكنك الوصول إلى هذا الجزء من وحدة التحكم باستخدام params[<:param>]
.
resources :videos, param: :identifier
videos GET /videos(.:format) videos#index
POST /videos(.:format) videos#create
new_videos GET /videos/new(.:format) videos#new
edit_videos GET /videos/:identifier/edit(.:format) videos#edit
Video.find_by(identifier: params[:identifier])
يمكنك استبدال ActiveRecord::Base#to_param
لنموذج ذي صلة لإنشاء عنوان URL:
class Video < ApplicationRecord
def to_param
identifier
end
end
video = Video.find_by(identifier: "Roman-Holiday")
edit_videos_path(video) # => "/videos/Roman-Holiday"
فحص واختبار المسارات الموجهة
توفر ريلز أدوات ووسائل لفحص واختبار المسارات الموجهة الخاصة بك.
قائمة المسارات الحالية
للحصول على قائمة كاملة بالمسارات المتاحة في التطبيق الخاص بك، قم بزيارة http://localhost:3000/rails/info/routes في المستعرض الخاص بك أثناء تشغيل خادمك في بيئة التطوير. يمكنك أيضًا تنفيذ الأمر rails routes
في الطرفية الخاصة بك لإنتاج نفس المخرجات.
ستقوم كلا الطريقتين بإدراج جميع مساراتك الموجهة بنفس الترتيب الذي تظهر به في config/routes.rb. لكل مسار، سترى:
- اسم المسار الموجه (إن وجد).
- الفعل HTTP المستخدم (إذا كان المسار لا يستجيب لكل الأفعال).
- نمط عنوان URL المراد مطابقته.
- معاملات التوجيه للمسار الموجه.
على سبيل المثال، إليك مقطع صغير من مخرجات الأمر rails routes
لمسار RESTful الموجه:
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
يمكنك البحث من خلال مساراتك الموجهة باستخدام الخيار grep: -g
. يظهر هذا الأمر أي مسارات موجهة تتطابق جزئيًا مع اسم تابع مساعد العنوان URL، أو فعل HTTP، أو مسار عنوان URL.
$ bin/rails routes -g new_comment
$ bin/rails routes -g POST
$ bin/rails routes -g admin
إذا كنت ترغب فقط في رؤية المسارات الموجهة التي تعين إلى وحدة تحكم معينة، فهناك الخيار -c
:
$ bin/rails routes -c users
$ bin/rails routes -c admin/users
$ bin/rails routes -c Comments
$ bin/rails routes -c Articles::CommentsController
فائدة: ستجد أن المخرجات من الأمر rails routes
أكثر قابلية للقراءة إذا قمت بتوسيع نافذة طرفيتك حتى لا تلتف سطور المخرجات.
اختبار المسارات الموجهة
يجب تضمين المسارات الموجهة في إستراتيجية الاختبار (تمامًا مثل بقية تطبيقك). تقدم ريلز ثلاثة تأكيدات مضمنة مصممة لجعل عملية اختبار المسارات الموجهة أكثر بساطة:
Assert_generates
Assert_recognizes
assert_routing
تأكيد assert_generates
يؤكد assert_generates
أن مجموعة معينة من الخيارات تولد مسارًا معينًا ويمكن استخدامها مع المسارات الافتراضية أو المسارات المخصصة. إليك المثال التالي:
assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' }
assert_generates '/about', controller: 'pages', action: 'about'
تأكيد assert_recognizes
هو عكس التأكيد assert_generates
، إذ يؤكد أنه جرى التعرف على مسار معين ووُجِّه إلى مكان معين في التطبيق الخاص بك. إليك المثال التالي:
assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1')
يمكنك توفير الوسيط method:
لتحديد فعل HTTP:
assert_recognizes({ controller: 'photos', action: 'create' }, { path: 'photos', method: :post })
تأكيد assert_routing
يتحقق تأكيد assert_routing
من الطريقتين: يختبر أن المسار يولد الخيارات، وأن الخيارات تولد المسار. وبالتالي، فهو يجمع بين وظائف assert_generates
و assert_recognizes
:
assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' })