تعرفنا في الدرس السابق على أهم الخدع، النصائح والتحذيرات وسنتابع في هذا الدرس مرجع الارتباط المفصّل.
4 مرجع الارتباط المفصّل
ستجد في الأقسام التالية تفاصيل حول كل نوع من أنواع الارتباط، بما في ذلك الأساليب التي تضيفها والخيارات التي يمكنك استخدامها عند إعلان الارتباط.
4.1 مرجع ارتباط belongs_to
ينشئ ارتباط belongs_to
تطابق واحد لواحد (one-to-one) مع نموذج آخر، بمصطلحات قاعد البيانات، يعني هذا الارتباط أن هذا الصنف يحتوي على مفتاح خارجي، إذا كان الصنف الآخر يحتوي على مفتاح خارجي، فيجب عليك في هذه الحالة استخدام has_one
بدلًا من ذلك.
4.1.1 أساليب مضافة بواسطة belongs_to
عند إعلان ارتباط belongs_to
، فسيحصل الصنف المعلن على 5 أساليب مرتبطة بالارتباط:
-
association
-
association=(associate)
-
({} = build_association(attributes
-
({} = create_association(attributes
-
({} = create_association!(attributes
-
reload_association
في جميع هذه النماذج، سيُستبدل الارتباط مع symbol
الذي مُرر كمعامل أول إلى belongs_to
، فعلى سبيل المثال، هذا الإعلان:
class Book < ApplicationRecord belongs_to :author end
سيحصل كل مثيل نموذج Book
على هذه الأساليب:
author author= build_author create_author create_author! reload_author
اقتباسملاحظة:
يجب عليك استخدم بادئة_build
عند تهيئة ارتباطhas_one
أوbelongs_to
لبناء الارتباط، بدلًا من أسلوبassociation.build
الذي يستخدم لارتباطاتhas_many
أوhas_and_belongs_to_many
، ولإنشاء واحد، استخدم بادئة_create
.
4.1.1.1 association
يرجع أسلوب association
الكائن المقترن إذا وجد، وإلا فسيُرجع nil
.
@author = @book.author
إذا أُسترد الكائن من قاعدة البيانات لهذا الكائن، ستُرجع النسخة المخبئة، ولتجاوز هذا السلوك (وإجبار القراءة من قاعدة البيانات)، استدعي reload_association#
في كائن الأب.
@author = @book.reload_author
4.1.1.2 (association=(associate
يعيّن أسلوب association=
كائن مرتبط لهذا الكائن، في ما وراء الكواليس، يعني هذا استخراج المفتاح الأساسي من الكائن المرتبط وتعيين قيمة المفتاح الخارجي للكائن لنفس قيمته.
@book.author = @author
4.1.1.3 ({} = build_association(attributes
يُرجع أسلوب build_association
كائن جديد لنوع المرتبط، هذا الكائن سيُنشئ من السمات المُمرّرة وسيُعين الارتباط من خلال المفتاح الخارجي لكن لن بعد يحفظ بعد الكائن المرتبط.
@author = @book.build_author(author_number: 123,
author_name: "John Doe")
4.1.1.4 ({} = create_association(attributes
سيرجع أسلوب create_association
كائن جديد لنوع المرتبط، هذا الكائن سيُنشئ من السمات المُمررة وسيُعين الارتباط من خلال المفتاح الخارجي، وبمجرد تمرير جميع عمليات التحقيق validations المحددة على النموذج المرتبط، سيُحفظ الكائن المرتبط.
@author = @book.create_author(author_number: 123,
author_name: "John Doe")
4.1.1.5 ({} = create_association!(attributes
يعمل كما create_association
في الأعلى، لكنه يُصدر ActiveRecord::RecordInvalid إذا كان السجل record غير صالح.
4.1.2 خيارات لـ belongs_to
في حين يستخدم Rails افتراضات ذكية ستعمل بشكل صحيح في أغلب الأحيان، ستحتاج في بعض الأحيان إلى تخصيص مرجع سلوك ارتباط belongs_to
، ويمكن تحقيق هذه التخصيصات بسهولة عن طريق تمرير الخيارات وكتل النطاق (scope) عند إنشاء الارتباط، فعلى سبيل المثال، هذا الارتباط يستخدم هذين الخيارين:
class Book < ApplicationRecord
belongs_to :author, dependent: :destroy,
counter_cache: true
end
يدعم ارتباط belongs_to
هذه الخيارات:
-
autosave:
-
class_name:
-
counter_cache:
-
dependent:
-
foreign_key:
-
primary_key:
-
inverse_of:
-
polymorphic:
-
touch:
-
validate:
-
optional:
4.1.2.1 autosave:
إذا عيّنت خيار autosave:
إلى true
، فسيحفظ Rails جميع أعضاء المحمّلين وسيدمر الأعضاء الذين وضع عليهم علامة التدمير كلما حفظت كائن الأب.
4.1.2.2 class_name:
إذا لم يكن بالإمكان اشتقاق اسم النموذج الآخر من اسم الارتباط، يمكنك استخدام خيار class_name:
لتوفير اسم النموذج، فعلى سبيل المثال، إذا كان الكتاب ينتمي إلى المؤلف، لكن اسم فعلي للنموذج الذي يحتوي على المؤلفين هو Patron
:
class Book < ApplicationRecord
belongs_to :author, class_name: "Patron"
end
4.1.2.3 counter_cache:
يمكنك استخدام خيار counter_cache:
لتجعل عملية العثور على عدد الكائنات التابعة أكثر كفاءة، على سبيل المثال هذه النماذج:
class Book < ApplicationRecord
belongs_to :author
end
class Author < ApplicationRecord
has_many :books
end
مع هذه الإعلانات، يتطلب طلب قيمة author.books.size@
الاتصال بقاعدة البيانات لتنفيذ استعلام (*)COUNT
، ولنتجنب هذا الاتصال، يمكنك إضافة ذاكرة مؤقتة لتخزين العدد إلى نموذج الانتماء:
class Book < ApplicationRecord
belongs_to :author, counter_cache: true
end
class Author < ApplicationRecord
has_many :books
end
مع هذا الإعلان، سيُبقي Rails قيمة الذاكرة المؤقتة مُحدّثة، وسيجيب بتلك القيمة عند الطلب من أسلوب size
.
على الرغم من تحديد خيار counter_cache:
في النموذج الذي يتضمن إعلان belongs_to
، يجب إضافة العمود الحالي إلى النموذج المرتبط (has_many
)، في الحالة أعلاه، ستحتاج إلى إضافة عمود باسم books_count
إلى نموذج Author
.
يمكنك تجاوز اسم الافتراضي للعمود من خلال تحديد اسم العمود المخصص في إعلان counter_cache
بدلا من true
، فعلى سبيل المثال، لاستخدام count_of_books
بدلا من books_count
:
class Book < ApplicationRecord
belongs_to :author, counter_cache: :count_of_books
end
class Author < ApplicationRecord
has_many :books
end
اقتباسملاحظة:
تحتاج إلى تحديد خيارcounter_cache:
في جانبbelongs_to
من الارتباط.
تضاف أعمدة ذاكرة التخزين المؤقت إلى قائمة النموذج التي تحتوي على سمات القراءة فقط من خلالattr_readonly
.
4.1.2.4 :dependent
إذا قمت بتعيين خيار dependent:
إلى:
-
destroy:
، عند تدمير الكائن، ستُستدعىdestroy
على الكائنات المرتبطة. -
delete:
، عند تدمير الكائن، ستُحذف جميع الكائنات المرتبطة بها مباشرة من قاعدة البيانات دون استدعاء أسلوبdestroy
.
اقتباستنبيه:
يجب عليك عدم تحديد هذا الخيار على ارتباطbelongs_to
المتصل مع ارتباطhas_many
على الصنف الآخر، لأنه قد يؤدي هذا إلى سجلات يتيمة في قاعدة البيانات.
4.1.2.5 foreign_key:
بالاتفاق، يفترض Rails أن العمود المستخدم لحمل المفتاح الخارجي في هذا النموذج هو اسم الارتباط مع إضافة بادئة id_
، خيار foreign_key:
يُتيح لك تعيين اسم المفتاح الخارجي مباشرة:
class Book < ApplicationRecord
belongs_to :author, class_name: "Patron",
foreign_key: "patron_id"
end
اقتباسملاحظة:
في أي حال، لن ينشئ Rails عمود المفتاح الخارجي لك، ستحتاج إلى تعريفهم بشكل صريح كجزء من عمليات التهجير.
4.1.2.6 primary_key:
بالاتفاق، يفترض Rails أن عمود id
يُستخدم لاحتواء المفتاح الرئيسي للجداول، ويسمح لك خيار primary_key:
بتحديد عمود مختلف.
على سبيل المثال، إذا كان لدينا جدول users
مع guid
كمفتاح رئيسي، أردنا جدول todos
منفصل لاحتواء المفتاح الخارجي user_id
في عمود guid
، ثم يمكننا استخدام primary_key
لتحقيق ما يشابه هذا:
class User < ApplicationRecord
self.primary_key = 'guid' # primary key is guid and not id
end
class Todo < ApplicationRecord
belongs_to :user, primary_key: 'guid'
end
عند تنفيذ user.todos.create@
فستكون قيمة user_id
في سجل todo@
كقيمة guid
في user@
.
4.1.2.7 inverse_of:
يحدد خيار inverse_of:
اسم عكس هذا الارتباط وهي has_many
أو has_one
، وهذه لا تعمل في التركيبة مع خيارات polymorphic:
class Author < ApplicationRecord
has_many :books, inverse_of: :author
end
class Book < ApplicationRecord
belongs_to :author, inverse_of: :books
end
4.1.2.8 polymorphic:
يشير تمرير true
إلى خيار polymorphic:
إلى أن الارتباط متعدد الأشكال، وسنتحدث عن الارتباطات متعدد الأشكال لاحقا في هذا الدليل.
4.1.2.9 touch:
إذا عيّنت خيار touch:
إلى true
، فإن timestamp
لـ updated_at
أو updated_on
في كائن المرتبط سيُعيّن إلى الوقت الحالي كلما حُفظ الكائن أو دُمر:
class Book < ApplicationRecord
belongs_to :author, touch: true
end
class Author < ApplicationRecord
has_many :books
end
في هذه الحالة، حفظ أو تدمير كتاب سيٌحدّث timestamp
في المؤلف المرتبط به، يمكنك أيضًا تحديد سمة timestamp
معينة للتحديث:
class Book < ApplicationRecord
belongs_to :author, touch: :books_updated_at
end
4.1.2.10 validate:
إذا عيّنت خيار validate:
إلى true
، فسيتحقق (Validate) الكائنات المرتبطة كلما حفظت هذا الكائن. وهذا الخيار يساوي false
بشكل افتراضي، ولن يتحقق الكائنات المرتبطة عند حفظ الكائن.
4.1.2.11 optional:
إذا عيّنت خيار optional:
إلى true
، فلن يتحقق من وجود الكائن المرتبط، وهذا الخيار false بشكل افتراضي.
4.1.3 نطاقات Scopes لـ belongs_to
في بعض الأحيان قد تحتاج إلى تخصيص الاستعلام المُستخدم من قبل belongs_to
، ويمكن تحقيق هذه التخصيصات عن طريق كتلة scope
، فعلى سبيل المثال:
class Book < ApplicationRecord
belongs_to :author, -> { where active: true },
dependent: :destroy
end
يمكنك استخدام أي من أساليب الاستعلامات القياسية داخل كتلة scope
، وستجد تفاصيل التالية في الأسفل:
-
where
-
includes
-
readonly
-
select
4.1.3.1 where
يسمح لك أسلوب where
بتحديد شروط كائن المرتبط.
class book < ApplicationRecord
belongs_to :author, -> { where active: true }
end
4.1.3.2 includes
يمكنك استخدام أسلوب includes
لتحديد الارتباطات من الدرجة الثانية التي تريد تحميلها (eager-loaded
) عند استخدام هذا الارتباط، فعلى سبيل المثال، فكر في هذه النماذج:
class LineItem < ApplicationRecord
belongs_to :book
end
class Book < ApplicationRecord
belongs_to :author
has_many :line_items
end
class Author < ApplicationRecord
has_many :books
end
إذا كنت تسترد المؤلفين مباشرة من سطر العناصر بشكل كثير (line_item.book.author@
)، فيمكنك جعل شيفرتك البرمجية أكثر كفاءة من خلال تضمين المؤلفين إلى الارتباط من سطر العناصر إلى الكتب:
class LineItem < ApplicationRecord
belongs_to :book, -> { includes :author }
end
class Book < ApplicationRecord
belongs_to :author
has_many :line_items
end
class Author < ApplicationRecord
has_many :books
end
اقتباسملاحظة:
لا حاجة إلى استخدامincludes
للارتباطات الفورية، فإذا كان لديكBook belongs_to :author
فيُحمل المؤلف (eager-loaded
) بشكل تلقائي عند الحاجة.
4.1.3.3 readonly
سيكون الكائن المرتبط قابل للقراءة فقط عند استرداده عن طريق الارتباط إذا استخدمت readonly
.
4.1.3.4 select
يسمح لك أسلوب select
بتجاوز جملة SELECT
(في SQL) والتي تُستخدم لاسترداد البيانات حول الكائن المرتبط، وبشكل افتراضي، سيسترد Rails جميع الأعمدة.
اقتباسملاحظة:
إذا استخدمت أسلوبselect
على ارتباطbelongs_to
، يجب عليك تعيين خيار:foreign_key
لضمان صحّة النتائج.
4.1.4 هل توجد أية كائنات مرتبطة؟
يمكنك معرفة هل توجد أية كائنات مرتبطة عن طريقة استخدام أسلوب ?association.nil
:
if @book.author.nil?
@msg = "No author found for this book"
end
4.1.5 متى تُحفظ الكائنات؟
إن تعيين كائن إلى ارتباط belongs_to
لن يحفظ الكائن بشكل تلقائي، ولن يحفظ كائن المرتبط أيضًا.
وسنتابع في الدرس القادم من هذه السلسلة الحديث عن مرجع ارتباط has_one
المصدر:
توثيقات Ruby on Rails
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.