مقدمة
روبي على ريلز هو إطار تطبيق ويب مكتوب بلغة روبي يقدم للمطورين نهجًا محدد الرأي لتطوير التطبيقات. يوفر العمل مع ريلز:
- توجيهات لمعالجة الأمور مثل التوجيه، والبيانات القابلة للتخزين، وإدارة الموارد.
- A firm grounding in the model-view-controller (MCV) architectural pattern, which separates an application’s logic, located in models, from the presentation and routing of application information.
مع زيادة التعقيد في تطبيقات ريلز الخاصة بك، من المحتمل أن تعمل مع عدة نماذج، التي تمثل منطق تطبيقك وتتفاعل مع قاعدة البيانات الخاصة بك. إضافة نماذج ذات علاقة يعني إقامة علاقات معنوية بينها، والتي بدورها تؤثر على كيفية تمرير المعلومات من خلال وحدات التحكم في تطبيقك، وكيفية التقاطها وعرضها مرة أخرى للمستخدمين من خلال العرض.
في هذا البرنامج التعليمي، ستعمل على توسيع تطبيق ريلز موجود يقدم للمستخدمين حقائق عن القروش. يحتوي هذا التطبيق بالفعل على نموذج لمعالجة بيانات القرش، ولكن ستضيف موردًا مدمجًا للمنشورات حول القروش الفردية. سيتيح هذا للمستخدمين بناء مجموعة واسعة من الأفكار والآراء حول القروش الفردية.
المتطلبات المسبقة
لمتابعة هذا البرنامج التعليمي، ستحتاج إلى:
- A local machine or development server running Ubuntu 18.04. Your development machine should have a non-root user with administrative privileges and a firewall configured with
ufw
. For instructions on how to set this up, see our Initial Server Setup with Ubuntu 18.04 tutorial. - تم تثبيت Node.js و npm على جهازك المحلي أو الخادم التطويري. يستخدم هذا البرنامج التعليمي إصدار 10.16.3 من Node.js وإصدار 6.9.0 من npm. للإرشادات حول تثبيت Node.js وnpm على Ubuntu 18.04، اتبع التعليمات في قسم “تثبيت باستخدام PPA” من كيفية تثبيت Node.js على Ubuntu 18.04.
- يجب أن يكون لديك Ruby و rbenv و Rails مثبتة على جهازك المحلي أو الخادم التطويري، وفقًا للخطوات 1-4 في كيفية تثبيت Ruby on Rails باستخدام rbenv على Ubuntu 18.04. يستخدم هذا البرنامج التعليمي Ruby 2.5.1، و rbenv 1.1.2، و Rails 5.2.3.
- يجب أن يكون SQLite مثبتًا، وتم إنشاء تطبيق معلومات أسماك أساسي، وفقًا للتوجيهات في كيفية بناء تطبيق Ruby on Rails.
الخطوة 1 — بناء النموذج المتداخل
سيستفيد تطبيقنا من تجميع Active Record الارتباطات لبناء علاقة بين نماذج Shark
و Post
: ستنتمي المشاركات إلى أسماك معينة، ويمكن لكل سمكة أن تمتلك عدة مشاركات. بالتالي، ستكون نماذجنا Shark
و Post
مرتبطة بواسطة الارتباطات belongs_to
و has_many
.
الخطوة الأولى في بناء التطبيق بهذه الطريقة ستكون إنشاء نموذج Post
والموارد ذات الصلة. للقيام بذلك، يمكننا استخدام أمر rails generate scaffold
، الذي سيمنحنا نموذجًا، وتحول جدول قاعدة البيانات لتغيير بنية القاعدة، ومتحكم، ومجموعة كاملة من العروض لإدارة العمليات القياسية إنشاء، قراءة، تحديث، وحذف (CRUD)، وقوالب للأجزاء الجزئية، والمساعدين، والاختبارات. سنحتاج إلى تعديل هذه الموارد، ولكن باستخدام أمر scaffold
سيوفر لنا بعض الوقت والطاقة حيث يولد هيكلًا يمكننا استخدامه كنقطة انطلاق.
أولاً، تأكد من أنك في دليل sharkapp
لمشروع Rails الذي أنشأته في المتطلبات الأساسية:
قم بإنشاء موارد Post
الخاصة بك باستخدام الأمر التالي:
rails generate scaffold Post body:text shark:references
با `body:text
`، نخبر Rails بتضمين حقل `body
` في جدول قاعدة البيانات `posts
` — الجدول الذي يتطابق مع نموذج `Post
`. كما نضمن أيضًا استخدام الكلمة الرئيسية `:references
`، التي تُعد الجمع بين نماذج `Shark
` و `Post
`. تحديداً، سيضمن هذا وجود مفتاح أجنبي يمثل كل إدخال لسمكة في قاعدة البيانات `sharks
` في قاعدة البيانات `posts
`.
بمجرد تشغيل الأمر، سترى إخراجًا يؤكد الموارد التي أنشأها Rails للتطبيق. قبل المضي قدمًا، يمكنك التحقق من ملف الترحيل الخاص بقاعدة البيانات للاطلاع على العلاقة التي توجد الآن بين نماذجك وجداول قاعدة البيانات. استخدم الأمر التالي لعرض محتويات الملف، متأكدًا من استبدال الطابع الزمني على ملف الترحيل الخاص بك بما هو معروض هنا:
سترى الناتج التالي:
Outputclass CreatePosts < ActiveRecord::Migration[5.2]
def change
create_table :posts do |t|
t.text :body
t.references :shark, foreign_key: true
t.timestamps
end
end
end
كما ترى، يتضمن الجدول عمودًا لمفتاح أجنبي لسمكة. سيأخذ هذا المفتاح الشكل `model_name_id
` — في حالتنا، `shark_id
`.
قامت Rails بإنشاء العلاقة بين النماذج في أماكن أخرى أيضًا. انظر إلى نموذج `Post
` الجديد الذي تم إنشاؤه مع الأمر التالي:
cat app/models/post.rb
Outputclass Post < ApplicationRecord
belongs_to :shark
end
تُعيد الجمعية `belongs_to
` إعداد علاقة بين النماذج حيث ينتمي مثيل واحد من النموذج المعلن إلى مثيل واحد من النموذج المسمى. في حالة تطبيقنا، يعني هذا أن مشاركة واحدة تنتمي إلى سمكة واحدة.
بالإضافة إلى تعيين هذا العلاقة، أنشأت أيضًا الأوامر rails generate scaffold
طرق وعروض للمنشورات، كما فعلت لموارد القرش في الخطوة 3 من كيفية بناء تطبيق Ruby on Rails.
هذا بداية مفيدة، ولكن سنحتاج إلى تكوين بعض التوجيهات الإضافية وترسيخ العلاقة النشطة لنموذج Shark
من أجل عمل العلاقة بين نماذجنا والطرق كما نرغب.
الخطوة 2 — تحديد التوجيهات المتداخلة والعلاقات للنموذج الأم
لقد قامت Rails بتعيين العلاقة belongs_to
بالفعل في نموذج Post
لدينا، بفضل الكلمة الرئيسية :references
في أمر rails generate scaffold
، ولكن من أجل أن تعمل هذه العلاقة بشكل صحيح، سنحتاج أيضًا إلى تحديد علاقة has_many
في نموذج Shark
لدينا أيضًا. سنحتاج أيضًا إلى إجراء تغييرات في التوجيه الافتراضي الذي قدمته Rails لنا من أجل جعل موارد المنشورات أطفال موارد القرش.
لإضافة الجمعية has_many
إلى نموذج Shark
، افتح app/models/shark.rb
باستخدام nano
أو محررك المفضل:
أضف السطر التالي إلى الملف لتأسيس العلاقة بين الأسماك القرشية والمشاركات:
class Shark < ApplicationRecord
has_many :posts
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
شيء واحد يستحق التفكير هنا هو ما يحدث للمشاركات بمجرد حذف قرش معين. من المحتمل أننا لا نرغب في استمرار المشاركات المرتبطة بقرش محذوف في قاعدة البيانات. لضمان حذف أي مشاركات مرتبطة بقرش معين عند حذف ذلك القرش، يمكننا تضمين الخيار dependent
مع الجمعية.
أضف الكود التالي إلى الملف لضمان أن الإجراء destroy
على قرش معين يحذف أي مشاركات مرتبطة:
class Shark < ApplicationRecord
has_many :posts , dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :facts, presence: true
end
بمجرد الانتهاء من إجراء هذه التغييرات، احفظ وأغلق الملف. إذا كنت تستخدم nano
، يمكنك القيام بذلك عن طريق الضغط على CTRL+X
، ثم Y
، ثم ENTER
.
بعد ذلك، افتح ملف config/routes.rb
لتعديل العلاقة بين مسارات الموارد الخاصة بك:
حاليًا، يبدو الملف كما يلي:
Rails.application.routes.draw do
resources :posts
resources :sharks
root 'sharks#index'
# لمزيد من التفاصيل حول DSL المتاحة في هذا الملف، انظر إلى http://guides.rubyonrails.org/routing.html
end
الكود الحالي ينشئ علاقة مستقلة بين مساراتنا، عندما نريد التعبير عن علاقة تابعة بين القروش ومشاركاتها.
لنقم بتحديث إعلان المسار الخاص بنا لجعل :sharks
الأب لـ :posts
. قم بتحديث الكود في الملف ليبدو كما يلي:
Rails.application.routes.draw do
resources :sharks do
resources :posts
end
root 'sharks#index'
# للحصول على تفاصيل حول لغة التوجيه المتاحة في هذا الملف، انظر http://guides.rubyonrails.org/routing.html
end
احفظ الملف وأغلقه عند الانتهاء من التحرير.
بعد تحديث هذه التغييرات، يمكنك المضي قدما في تحديث متحكم posts
الخاص بك.
الخطوة 3 — تحديث متحكم المنشورات
الارتباط بين نماذجنا يعطينا أساليب يمكننا استخدامها لإنشاء مثيلات منشور جديدة مرتبطة بأسماك معينة. لاستخدام هذه الأساليب، سنحتاج إلى إضافتها إلى متحكم المنشورات الخاص بنا.
افتح ملف متحكم المنشورات:
حاليا، يبدو الملف كما يلي:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# احصل على /مقالات
# احصل على /مقالات.json
def index
@posts = Post.all
end
# احصل على /مقالات/1
# احصل على /مقالات/1.json
def show
end
# احصل على /مقالات/new
def new
@post = Post.new
end
# احصل على /مقالات/1/edit
def edit
end
# ارسل /مقالات
# ارسل /مقالات.json
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# اصلاح/ضع /مقالات/1
# اصلاح/ضع /مقالات/1.json
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# حذف /مقالات/1
# حذف /مقالات/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# استخدم الاستدعاءات لمشاركة الإعدادات المشتركة أو القيود بين الإجراءات.
def set_post
@post = Post.find(params[:id])
end
# لا تثق أبدًا بالمعلمات من الإنترنت المخيف، فقط السماح بالقائمة البيضاء من خلاله.
def post_params
params.require(:post).permit(:body, :shark_id)
end
end
مثل مُتحكم القروش لدينا، تعمل طرق هذا المُتحكم مع مثيلات فئة المقالة
المُرتبطة. على سبيل المثال، يُنشئ الطريقة جديد
مثيلًا جديدًا من فئة المقالة
، وتقوم الطريقة الفهرس
بجلب جميع المثيلات من الفئة، وتستخدم الطريقة ضبط_المقالة
find
و params
لتحديد مقالة معينة بواسطة id
. إذا كنا نريد، ومع ذلك، أن تكون مثيلات المقالات لدينا مرتبطة بمثيلات أسماك معينة، سنحتاج إلى تعديل هذا الكود، حيث أن فئة المقالة
تعمل حاليًا ككيان مستقل.
سيقوم تعديلاتنا باستخدام شيئين:
- الطرق التي أصبحت متاحة لنا عندما أضفنا التجمعات
belongs_to
وhas_many
إلى نماذجنا. على وجه التحديد، لدينا الآن الوصول إلى طريقةbuild
بفضل الارتباطhas_many
الذي قمنا بتعريفه في نموذجناShark
. ستسمح لنا هذه الطريقة بإنشاء مجموعة من كائنات المنشور المرتبطة بكائن سمكة معين، باستخدام المفتاح الخارجيshark_id
الذي يوجد في قاعدة البيانات الخاصة بناposts
. - المسارات ومساعدي التوجيه التي أصبحت متاحة عندما قمنا بإنشاء مسار
posts
متداخل. للحصول على قائمة كاملة من المسارات المثالية التي تصبح متاحة عند إنشاء علاقات متداخلة بين الموارد، انظر إلى توثيق ريلز. في الوقت الحالي، سيكون من الكافي بالنسبة لنا أن نعرف أنه لكل سمكة محددة — مثلsharks/1
— سيكون هناك مسار مرتبط للمنشورات المتعلقة بهذه السمكة:sharks/1/posts
. كما ستكون هناك مساعدي توجيه مثلshark_posts_path(@shark)
وedit_sharks_posts_path(@shark)
التي تشير إلى هذه المسارات المتداخلة.
في الملف، سنبدأ بكتابة طريقة، get_shark
، التي ستقوم بتشغيلها قبل كل إجراء في المتحكم. ستقوم هذه الطريقة بإنشاء متغير محلي @shark
عن طريق العثور على مثيل سمكة بواسطة shark_id
. بتوفر هذا المتغير لنا في الملف، سيكون من الممكن ربط المنشورات بسمكة محددة في الطرق الأخرى.
فوق باقي الطرق الخاصة الأخرى في الجزء السفلي من الملف، أضف الطريقة التالية:
. . .
private
def get_shark
@shark = Shark.find(params[:shark_id])
end
# استخدم مراجع الاستدعاء لمشاركة الإعداد الشائع أو القيود بين الإجراءات.
. . .
بعد ذلك، أضف الفلتر المقابل إلى الأعلى من الملف، قبل الفلتر الموجود بالفعل:
class PostsController < ApplicationController
before_action :get_shark
سيضمن هذا أن تشغل get_shark
قبل كل إجراء محدد في الملف.
بعد ذلك، يمكنك استخدام هذه النسخة @shark
لإعادة كتابة الطريقة index
. بدلاً من جلب كافة حالات فئة Post
، نريد أن تُرجع هذه الطريقة كافة حالات المشاركة المرتبطة بنسخة معينة من سمكة.
عدل الطريقة index
لتبدو مثل هذا:
. . .
def index
@posts = @shark.posts
end
. . .
ستحتاج الطريقة new
إلى تعديل مماثل، حيث نريد أن يتم ربط نسخة جديدة من المشاركة بسمكة محددة. لتحقيق ذلك، يمكننا استخدام الطريقة build
مع متغير النسخة المحلي @shark
.
قم بتغيير الطريقة new
لتبدو كما يلي:
. . .
def new
@post = @shark.posts.build
end
. . .
تنشئ هذه الطريقة كائن مشاركة مرتبط بالسمكة المحددة من طريقة get_shark
.
بعد ذلك، سنتناول الطريقة التي ترتبط بشكل أقرب بـ new
: create
. تقوم طريقة create
بشيئين: إنشاء كائن مشاركة جديد باستخدام المعلمات التي أدخلها المستخدمون في النموذج new
، وإذا كانت هناك أخطاء، فإنها تقوم بحفظ تلك النسخة واستخدام مساعد مسار لتوجيه المستخدمين إلى حيث يمكنهم رؤية المشاركة الجديدة. في حالة الأخطاء، فإنها تقوم بعرض النموذج new
مرة أخرى.
تحديث طريقة create
لتبدو كالتالي:
def create
@post = @shark.posts.build(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
بعد ذلك، ألقِ نظرة على طريقة update
. تستخدم هذه الطريقة متغير @post
، الذي لم يتم تعيينه بشكل صريح في الطريقة نفسها. من أين يأتي هذا المتغير؟
ألقِ نظرة على المرشحات في أعلى الملف. المرشح الثاني، المولد تلقائيًا before_action
، يوفر الإجابة:
class PostsController < ApplicationController
before_action :get_shark
before_action :set_post, only: [:show, :edit, :update, :destroy]
. . .
تأخذ طريقة update
(مثل show
، edit
، و destroy
) متغير @post
من طريقة set_post
. تبدو هذه الطريقة، المُدرجة تحت طريقة get_shark
مع طرقنا الخاصة الأخرى private
، حاليًا كالتالي:
. . .
private
. . .
def set_post
@post = Post.find(params[:id])
end
. . .
تماشيًا مع الطرق التي استخدمناها في أماكن أخرى في الملف، سنحتاج إلى تعديل هذه الطريقة بحيث يشير @post
إلى نسخة معينة في مجموعة المنشورات المرتبطة بسمكة معينة. تذكر الطريقة build
هنا — بفضل العلاقات بين نماذجنا، والطرق (مثل build
) التي تتوفر لنا بفضل هذه العلاقات، كل من مثيلات منشورنا هي جزء من مجموعة من الكائنات التي ترتبط بسمكة معينة. لذلك من المنطقي أنه عند الاستعلام عن منشور معين، سنستعلم عن مجموعة المنشورات المرتبطة بسمكة معينة.
قم بتحديث set_post
لتبدو كالتالي:
. . .
private
. . .
def set_post
@post = @shark.posts.find(params[:id])
end
. . .
بدلاً من البحث عن نسخة معينة من فئة Post
بواسطة id
، نقوم بالبحث عن id
مطابق في مجموعة المنشورات المرتبطة بسمكة معينة.
بعد تحديث هذه الطريقة، يمكننا النظر في الأساليب update
و destroy
.
تستخدم الأسلوب update
المتغير الحالي @post
من set_post
، وتستخدمه مع post_params
التي قام المستخدم بإدخالها في نموذج edit
. في حالة النجاح، نريد من Rails أن تعيد المستخدم إلى عرض index
للمشاركات المرتبطة بسمكة معينة. في حالة الأخطاء، ستقوم Rails بإعادة عرض القالب edit
مرة أخرى.
في هذه الحالة، الأمر الوحيد الذي سنحتاج إلى تغييره هو بيان redirect_to
، لمعالجة التحديثات الناجحة. قم بتحديثه ليعيد توجيهه إلى shark_post_path(@shark)
، الذي سيعيد التوجيه إلى عرض index
لمشاركات السمكة المحددة:
. . .
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
. . .
بعد ذلك، سنقوم بإجراء تغيير مماثل على الأسلوب destroy
. قم بتحديث أسلوب redirect_to
ليعيد توجيه الطلبات إلى shark_posts_path(@shark)
في حالة النجاح:
. . .
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
. . .
هذه هي آخر تغييرات سنقوم بها. الآن لديك ملف تحكم بالمشاركات يبدو مثل هذا:
class PostsController < ApplicationController
before_action :get_shark
before_action :set_post, only: [:show, :edit, :update, :destroy]
# الحصول على /منشورات
# الحصول على /منشورات.json
def index
@posts = @shark.posts
end
# الحصول على /منشورات/1
# الحصول على /منشورات/1.json
def show
end
# الحصول على /منشورات/new
def new
@post = @shark.posts.build
end
# الحصول على /منشورات/1/edit
def edit
end
# إرسال /منشورات
# إرسال /منشورات.json
def create
@post = @shark.posts.build(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# تعديل/وضع /منشورات/1
# تعديل/وضع /منشورات/1.json
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# حذف /منشورات/1
# حذف /منشورات/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def get_shark
@shark = Shark.find(params[:shark_id])
end
# استخدام مراجع الاستدعاء لمشاركة الإعدادات المشتركة أو القيود بين الإجراءات.
def set_post
@post = @shark.posts.find(params[:id])
end
# لا تثق أبدًا في المعلمات من الإنترنت المخيفة ، دع القائمة البيضاء فقط تمر.
def post_params
params.require(:post).permit(:body, :shark_id)
end
end
يدير المتحكم كيفية تمرير المعلومات من قوالب العرض إلى قاعدة البيانات والعكس بالعكس. يعكس متحكمنا الآن العلاقة بين نماذج Shark
و Post
، حيث ترتبط المنشورات بأسماك القرش الخاصة. يمكننا المضي قدمًا في تعديل قوالب العرض نفسها ، حيث يمكن للمستخدمين تمرير المعلومات وتعديلها حول المنشورات المتعلقة بأسماك القرش الخاصة بهم.
الخطوة 4 — تعديل العروض
ستشمل مراجعات قوالب العرض لدينا تغيير القوالب المتعلقة بالمنشورات ، وتعديل عرض أسماك القرش لدينا show
، حيث نريد من المستخدمين رؤية المنشورات المرتبطة بأسماك القرش المعينة.
لنبدأ مع القالب الأساسي لمنشوراتنا: الجزء الجزئي form
الذي يعاد استخدامه عبر العديد من قوالب المنشورات. افتح هذا النموذج الآن:
بدلاً من تمرير نموذج الـpost
فقط إلى مساعد النموذج form_with
، سنمرر كل من نماذج shark
و post
، مع تعيين post
كموروث فرعي.
قم بتغيير السطر الأول في الملف ليبدو بهذا الشكل، مع انعكاس العلاقة بين مواردنا للقرش والمنشور:
<%= form_with(model: [@shark, post], local: true) do |form| %>
. . .
بعد ذلك، احذف القسم الذي يقوم بسرد shark_id
للقرش المتعلق، حيث أن هذه المعلومات ليست ضرورية في العرض.
ستبدو النموذج المكتمل، مع التعديلات على السطر الأول وبدون قسم shark_id
المحذوف، بهذا الشكل:
<%= form_with(model: [@shark, post], local: true) do |form| %>
<% if post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
احفظ وأغلق الملف عند الانتهاء من التحرير.
بعد ذلك، افتح عرض index
، الذي سيري عناوين المنشورات المرتبطة بقرش معين:
بفضل أمر rails generate scaffold
، قامت Rails بتوليد الجزء الأفضل من القالب، مكتملًا مع جدول يعرض حقل body
لكل منشور وقرشه المرتبط.
ومع ذلك، على غرار الشفرة الأخرى التي قمنا بتعديلها بالفعل، يعامل هذا القالب المنشورات ككيانات مستقلة، عندما نود الاستفادة من العلاقات بين نماذجنا والمجموعات وطرق المساعد التي تعطينا هذه العلاقات.
في جسم الجدول، قم بعمل التحديثات التالية:
أولاً، قم بتحديث post.shark
إلى post.shark.name
، بحيث يتم تضمين حقل الاسم للقرش المرتبط، بدلاً من المعلومات المعرفة حول كائن القرش نفسه:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
. . .
ثم، قم بتغيير إعادة التوجيه Show
لتوجيه المستخدمين مباشرة إلى عرض القرش المرتبط، حيث من المحتمل أن يرغبوا في وسيلة للعودة إلى القرش الأصلي. يمكننا الاستفادة من المتغير المثيل @shark
الذي قمنا بتعيينه في المتحكم هنا، حيث يجعل Rails المتغيرات المثيلة التي تم إنشاؤها في المتحكم متاحة لجميع العروض. كما سنقوم بتغيير نص الرابط من Show
إلى Show Shark
، حتى يفهم المستخدمون وظيفته بشكل أفضل.
قم بتحديث هذا السطر إلى الشكل التالي:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
في السطر التالي، نريد التأكد من توجيه المستخدمين إلى المسار المتداخل الصحيح عندما يقومون بتحرير مشاركة. هذا يعني أنه بدلاً من توجيههم إلى posts/post_id/edit
، سيتم توجيه المستخدمين إلى sharks/shark_id/posts/post_id/edit
. للقيام بذلك، سنستخدم مساعد التوجيه shark_post_path
ونماذجنا، التي ستعتبرها Rails عناوين URL. كما سنقوم بتحديث نص الرابط لجعل وظيفته أكثر وضوحًا.
قم بتحديث السطر Edit
ليبدو كالتالي:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
المقبل، دعنا نضيف تغييرًا مماثلاً لرابط Destroy
، بتحديث وظيفته في السلسلة، وإضافة مواردنا shark
و post
:
. . .
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
<td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
أخيرًا، في أسفل النموذج، سنريد تحديث مسار New Post
لتوجيه المستخدمين إلى المسار المتداخل المناسب عندما يرغبون في إنشاء مشاركة جديدة. قم بتحديث السطر الأخير من الملف لاستخدام مساعد التوجيه new_shark_post_path(@shark)
:
. . .
<%= link_to 'New Post', new_shark_post_path(@shark) %>
الملف النهائي سيبدو بهذا الشكل:
<p id="notice"><%= notice %></p>
<h1>Posts</h1>
<table>
<thead>
<tr>
<th>Body</th>
<th>Shark</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.body %></td>
<td><%= post.shark.name %></td>
<td><%= link_to 'Show Shark', [@shark] %></td>
<td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
<td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_shark_post_path(@shark) %>
احفظ وأغلق الملف عند الانتهاء من التحرير.
لن تكون التعديلات الأخرى التي سنقوم بها على عرض المشاركات متعددة بنفس القدر، حيث أن عروضنا الأخرى تستخدم الجزء الجزئي form
الذي قمنا بتعديله بالفعل. ومع ذلك، سنرغب في تحديث مراجع link_to
في قوالب المشاركات الأخرى ليعكس التغييرات التي قمنا بها على الجزء الجزئي form
الخاص بنا.
افتح app/views/posts/new.html.erb
:
قم بتحديث مرجع link_to
في أسفل الملف لاستخدام مساعد shark_posts_path(@shark)
:
. . .
<%= link_to 'Back', shark_posts_path(@shark) %>
احفظ وأغلق الملف عند الانتهاء من إجراء هذا التغيير.
بعد ذلك، افتح قالب edit
:
بالإضافة إلى مسار Back
، سنقوم بتحديث Show
ليعكس مواردنا المتداخلة. قم بتغيير السطرين الأخيرين من الملف ليبدوا هكذا:
. . .
<%= link_to 'Show', [@shark, @post] %> |
<%= link_to 'Back', shark_posts_path(@shark) %>
احفظ وأغلق الملف.
بعد ذلك، افتح قالب show
:
nano app/views/posts/show.html.erb
قم بعمل التحريرات التالية على مسارات Edit
و Back
في أسفل الملف:
. . .
<%= link_to 'Edit', edit_shark_post_path(@shark, @post) %> |
<%= link_to 'Back', shark_posts_path(@shark) %>
احفظ وأغلق الملف عند الانتهاء.
كخطوة نهائية، سنرغب في تحديث عرض show
لأسماكنا حتى تكون المشاركات مرئية للأسماك الفردية. افتح ذلك الملف الآن:
ستتضمن تحريراتنا هنا إضافة قسم Posts
إلى النموذج ورابط Add Post
في أسفل الملف.
أدناه Facts
لسمكة معينة، سنقوم بإضافة قسم جديد يتجول عبر كل نموذج في مجموعة المنشورات المرتبطة بهذه السمكة، مخرجاً body
لكل منشور.
أضف الكود التالي أسفل قسم Facts
من النموذج، وفوق إعادات التوجيه في أسفل الملف:
. . .
<p>
<strong>Facts:</strong>
<%= @shark.facts %>
</p>
<h2>Posts</h2>
<% for post in @shark.posts %>
<ul>
<li><%= post.body %></li>
</ul>
<% end %>
<%= link_to 'Edit', edit_shark_path(@shark) %> |
. . .
بعد ذلك، أضف إعادة توجيه جديدة للسماح للمستخدمين بإضافة منشور جديد لهذه السمكة بالذات:
. . .
<%= link_to 'Edit', edit_shark_path(@shark) %> |
<%= link_to 'Add Post', shark_posts_path(@shark) %> |
<%= link_to 'Back', sharks_path %>
احفظ وأغلق الملف عند الانتهاء من التحرير.
لقد قمت الآن بإجراء تغييرات على نماذج تطبيقك ومتحكماته وعروضه لضمان أن المنشورات دائمًا مرتبطة بسمكة معينة. كخطوة نهائية، يمكننا إضافة بعض التحققات إلى نموذج Post
لضمان الاتساق في البيانات التي يتم حفظها في قاعدة البيانات.
الخطوة 5 — إضافة التحققات واختبار التطبيق
في الخطوة 5 من كيفية بناء تطبيق Ruby on Rails ، قمت بإضافة التحققات إلى نموذجك Shark
لضمان التوحيد والاتساق في البيانات التي يتم حفظها في قاعدة البيانات sharks
. سنقوم الآن بخطوة مماثلة لضمان الضمانات لقاعدة بيانات posts
أيضًا.
افتح الملف الذي يتم فيه تعريف نموذج Post
الخاص بك:
هنا، نريد التأكد من عدم فراغ المشاركات وعدم تكرار محتوى قد قام مستخدمون آخرون بنشره. لتحقيق ذلك، أضف السطر التالي إلى الملف:
class Post < ApplicationRecord
belongs_to :shark
validates :body, presence: true, uniqueness: true
end
احفظ وأغلق الملف عند الانتهاء من التحرير.
بهذا التغيير الأخير المُنفَّذ، أنت الآن جاهز لتشغيل التهجيرات واختبار التطبيق.
أولاً، قم بتشغيل التهجيرات الخاصة بك:
بعد ذلك، قم بتشغيل الخادم الخاص بك. إذا كنت تعمل محلياً، يمكنك القيام بذلك عن طريق تشغيل:
إذا كنت تعمل على خادم تطوير، قم بتشغيل الأمر التالي بدلاً من ذلك:
انتقل إلى جذر تطبيقك على الرابط http://localhost:3000
أو http://عنوان_خادمك_IP:3000
.
دلّت درس المشروع الأساسي لـ Rails على إضافة وتحرير إدخال لسمك القرش الأبيض الكبير. إذا لم تقم بإضافة أي أسماك قرش أخرى، ستكون صفحة الهبوط للتطبيق على النحو التالي:
انقر على إظهار بجانب اسم القرش الأبيض الكبير. سيأخذك ذلك إلى عرض show
لهذا القرش. سترى اسم القرش وحقائقه، ورأس المشاركات بدون محتوى. دعونا نضيف مشاركة لملء هذا الجزء من النموذج.
انقر على إضافة مشاركة أسفل رأس المشاركات. سيقودك ذلك إلى عرض الفهرس للمشاركات، حيث ستتاح لك الفرصة لتحديد مشاركة جديدة:
بفضل آليات المصادقة التي وضعتها في الخطوة 6 من كيفية بناء تطبيق Ruby on Rails، قد يُطلب منك المصادقة باستخدام اسم المستخدم وكلمة المرور التي أنشأتها في تلك الخطوة، اعتمادًا على ما إذا كنت قد أنشأت جلسة جديدة أم لا.
انقر على مشاركة جديدة، والتي ستوجهك إلى قالب new
لمشاركتك:
في حقل الجسم، اكتب “هذه القروش مخيفة!”
انقر على إنشاء مشاركة. ستتم إعادة توجيهك إلى عرض الفهرس لجميع المشاركات التي تنتمي إلى هذا القرش:
مع عمل موارد المشاركات لدينا، يمكننا الآن اختبار تحقق البيانات الخاص بنا لضمان حفظ البيانات المطلوبة فقط في قاعدة البيانات.
من عرض index
، انقر على مشاركة جديدة. في حقل الجسم للنموذج الجديد، حاول إدخال “هذه القروش مخيفة!” مرة أخرى:
انقر على إنشاء مشاركة. سترى الخطأ التالي:
انقر على العودة للعودة إلى الصفحة الرئيسية للمشاركات.
لاختبار التحقق من صحةنا الآخر، انقر على مشاركة جديدة مرة أخرى. اترك المشاركة فارغة وانقر على إنشاء مشاركة. سترى الخطأ التالي:
مع مواردك المتداخلة والتحقق من الصحة تعمل بشكل صحيح، لديك الآن تطبيق Rails يعمل يمكنك استخدامه كنقطة انطلاق للتطوير المستقبلي.
الاستنتاج
مع تطبيق Rails الخاص بك في مكانه، يمكنك الآن العمل على أشياء مثل التنسيق وتطوير مكونات واجهة المستخدم الأمامية الأخرى. إذا كنت ترغب في معرفة المزيد حول التوجيه والموارد المتداخلة، فإن توثيق Rails هو مكان رائع للبدء.
لمعرفة المزيد حول دمج الإطارات الأمامية مع تطبيقك، تفضل بالاطلاع على كيفية إعداد مشروع Ruby on Rails مع واجهة مستخدم أمامية React.