تابعنا في الدرس السابق من هذه السلسلة مرجع الارتباط المفصّل وسنتابع في هذا الدرس الحديث عن مرجع ارتباط has_one.
4.2 مرجع ارتباط has_one
يُنشئ ارتباط has_one
تطابق واحد لواحد (one-to-one) مع كائن آخر، بمصطلحات قاعدة البيانات، هذا الارتباط يعلن أن الصنف الآخر يحتوي على مفتاح خارجي، وإذا كان هذا الصنف يحتوي على مفتاح خارجي، فيجب عليك في هذه الحالة استخدام belongs_to
بدلا من ذلك.
4.2.1 الأساليب المضافة بواسطة has_one
عند إعلان ارتباط has_one
، فإن الفئة المُعلنة ستحصل على 5 أساليب متعلقة بالارتباط:
-
association
-
(association=(associate
-
({} = build_association(attributes
-
({} = create_association(attributes
-
({} = create_association!(attributes
-
reload_association
في كل هذه الأساليب، يُستبدل الارتباط مع symbol المُمرر كمعامل أول إلى has_one
، على سبيل المثال:
class Supplier < ApplicationRecord has_one :account end
فإن كل مثيل من نموذج Supplier
سيحصل على هذه الأساليب:
account account= build_account create_account create_account! reload_account
Quoteملاحظة:
يجب عليك عند إنشاء ارتباطhas_one
أوbelongs_to
جديد استخدام بادئة_build
لبناء الارتباط، بدلا من أسلوبassociation.build
الذي سيستخدم لارتباطاتhas_many
أوhas_and_belongs_to_many
، ولإنشاء واحد استخدم بادئة_create
.
4.2.1.1 association
يُرجع أسلوب association الكائن المرتبط إن وجد، وإلا، فسيرجع nil
.
@account = @supplier.account
إذا أُسترد الكائن المرتبط بالفعل من قاعدة البيانات لهذا الكائن، ستٌسترجع النسخة المخبأة، ولتجاوز هذا السلوك(وإجبار قاعدة البيانات على القراءة)، استدعي #reload_association
في الكائن الأب.
@account = @supplier.reload_account
4.2.1.2 (association=(associate
يُعيّن أسلوب =association
كائن مرتبط إلى هذا الكائن، وفي ما وراء الكواليس، هذا يعني استخراج المفتاح الرئيسي من هذا الكائن وتعيين مفتاح الخارجي للكائن المرتبطة إلى نفس القيمة.
@supplier.account = @account
4.2.1.3 ({} = build_association(attributes
يرجع أسلوب build_association
كائن جديد للنوع المرتبط، وهذا الكائن سيُنشئ من السمات المُمررة، وسيُعين الارتباط بمفتاحه الخارجي، لكن لن يُحفظ الكائن المرتبط.
@account = @supplier.build_account(terms: "Net 30")
4.2.1.4 ({} = create_association(attributes
يرجع أسلوب create_association
كائن جديد من النوع المرتبط، وهذا الكائن سيُنشئ من السمات الممررة، وسيُعين الارتباط بمفتاحه الخارجي، وبمجرد النجاح في جميع التحقيقات (validations) المحددة في النموذج المرتبط، سيُحفظ الكائن المرتبط.
@account = @supplier.create_account(terms: "Net 30")
4.2.1.5 ({} = create_association!(attributes
يعمل كما create_association
في الأعلى، لكنه يصدر ActiveRecord::RecordInvalid إذا كان السجل (record) غير صالح.
4-2-2 خيارات has_one
في حين يستخدم Rails الافتراضات الذكية والتي تعمل بشكل جيد في أغلب الأحيان، لكن في بعض الأوقات ستحتاج إلى تخصيص سلوك مرجع ارتباط has_one
، ويمكن تحقيق هذه التخصيصات بسهولة عن طريق تمرير الخيارات عند إنشاء الارتباط، فعلى سبيل المثال، يستخدم هذا الارتباط اثنين من هذه الخيارات:
class Supplier < ApplicationRecord has_one :account, class_name: "Billing", dependent: :nullify end
يدعم ارتباط has_one هذه الخيارات:
- as:
- autosave:
- class_name:
- dependent:
- foreign_key:
- inverse_of:
- primary_key:
- source:
- source_type:
- through:
- validate:
4.2.2.1 as:
يشير تعيين خيار as:
على أن الارتباط متعدد الأشكال، وستجد المزيد من التفاصيل حول الارتباطات متعددة الأشكال بالتفاصيل في الأعلى.
4.2.2.2 autosave:
إذا عيّنت خيار autosave:
إلى true
، فإن Rails سيحفظ أي أعضاء محملين وسيدمر الأعضاء الذي وُضع عليهما علامة للتدمير كلما حفظت كائن الأب.
4.2.2.3 class_name:
إذا لم يكن بالإمكان اشتقاق اسم النموذج الآخر من اسم الارتباط، يمكنك استخدام خيار class_name:
لتوفير اسم النموذج، فعلى سبيل المثال، إذا كان المُورّد يمتلك حساب، لكن اسم النموذج الحالي الذي يحتوي على الحسابات هو Billing، فيمكنك فعل التالي:
class Supplier < ApplicationRecord has_one :account, class_name: "Billing" end
4.2.2.4 dependent:
يتحكم في ما يحدث للكائن المرتبط عند حذف مالكه:
- destroy: سيدمر كائن المرتبط أيضا.
- delete: سيحذف الكائن المرتبط مباشرة من قاعدة البيانات (ولن يعمل دوال الاستدعاء).
- nullify: سيُعين المفتاح الخارجي إلى NULL ولن يعمل دوال الاستدعاء.
- restrict_with_exception: سيصدر استثناء إذا كان هنالك كائن مرتبط.
- restrict_with_error: سيضاف خطأ إلى المالك إذا كان هنالك كائن مرتبط.
من الضروري عدم تعيين أو ترك خيار nullify:
للارتباطات التي تملك قيود NOT NULL على قاعدة البيانات، إذا لم تعيّن dependent لتدمير هذه الارتباطات فلن تتمكن من تغيير كائن المرتبط لأنه سيُعيّن المفتاح الخارجي للكائن المرتبط الأولي إلى NULL التي هي غير مسموح بها.
4.2.2.5 foreign_key:
بالاتفاق، يفترض Rails أن العمود الذي يحمل المفتاح الخارجي في النموذج الآخر هو اسم النموذج مع إضافة بادئة id_
، ويسمح لك خيار :foreign_key
بتعيين اسم المفتاح الخارجي مباشرة:
class Supplier < ApplicationRecord has_one :account, foreign_key: "supp_id" end
Quoteتنبيه:
على أي حال، لن ينشئ Rails أعمدة مفتاح خارجي لك، ستحتاج إلى تعريف صريح لهم كجزء من التهجيرات.
4.2.2.6 inverse_of:
يحدد خيار inverse_of:
اسم ارتباط belongs_to
والذي هو عكس هذا الارتباط، وهذا الخيار لا يعمل في التركيبة مع خيارات through:
أو as:
.
class Supplier < ApplicationRecord has_one :account, inverse_of: :supplier end class Account < ApplicationRecord belongs_to :supplier, inverse_of: :account end
4.2.2.7 primary_key:
يفترض Rails أن العمود الذي يحمل المفتاح الرئيسي في هذا النموذج هو id
، يمكنك تجاوز ذلك وتصريح المفتاح الرئيسي عن طريق خيار primary_key:
4.2.2.8 source:
يحدد خيار source:
اسم ارتباط المصدر لارتباط has_one :through
.
4.2.2.9 source_type:
يحدد خيار source_type:
ارتباط المصدر لارتباط has_one :through
الذي يمر عبر ارتباط متعدد الأشكال.
4.2.2.10 through:
يحدد خيار through:
نموذج الضم والذي يتم من خلاله تنفيذ الاستعلام، تم الحديث حول has_one :through
في وقت سابق من هذا الدليل.
4.2.2.11 validate:
إذا عُيّن خيار validate:
إلى true
، فسيتحقق من الكائنات المرتبطة كلما حفظت هذا الكائن، افتراضيا، قيمة هذا الخيار هي false
، ولن يتحقق مع كائنات المرتبطة عند حفظ هذا الكائن.
4.2.3 نطاقات Scopes لـ belongs_to
في بعض الأحيان قد تحتاج إلى تخصيص الاستعلام المُستخدم من قبل has_one
، ويمكن تحقيق هذه التخصيصات عن طريق كتلة scope
، فعلى سبيل المثال:
class Supplier < ApplicationRecord has_one :account, -> { where active: true } end
يمكنك استخدام أي من أساليب الاستعلامات القياسية داخل كتلة scope
، وستجد تفاصيلها في الأسفل:
-
where
-
includes
-
readonly
-
select
4.2.3.1 where
يسمح لك أسلوب where
بتحديد شروط الكائن المرتبط.
class Supplier < ApplicationRecord has_one :account, -> { where "confirmed = 1" } end
4.2.3.2 includes
يمكنك استخدام أسلوب includes
لتحديد الارتباطات من الدرجة الثانية التي تريد تحميلها (eager-loaded
) عند استخدام هذا الارتباط، فعلى سبيل المثال، فكر في هذه النماذج:
class Supplier < ApplicationRecord has_one :account end class Account < ApplicationRecord belongs_to :supplier belongs_to :representative end class Representative < ApplicationRecord has_many :accounts end
إذا كنت تسترد الممثلين مباشرة من المُوردين بشكل كثير (supplier.account.representative@
)، فيمكنك جعل شيفرتك البرمجية أكثر كفاءة من خلال تضمين الممثلين إلى الارتباط من المُوردين إلى الحسابات:
class Supplier < ApplicationRecord has_one :account, -> { includes :representative } end class Account < ApplicationRecord belongs_to :supplier belongs_to :representative end class Representative < ApplicationRecord has_many :accounts end
4.2.3.3 readonly
سيكون الكائن المرتبط للقراءة فقط عند استرداده عن طريق الارتباط إذا استخدمت readonly
.
4.2.3.4 select
يسمح لك أسلوب select
بتجاوز جملة SELECT
(في SQL) والتي تُستخدم لاسترداد البيانات حول الكائن المرتبط، وبشكل افتراضي، سيسترد Rails جميع الأعمدة.
4.2.4 هل توجد أية كائنات مرتبطة؟
يمكنك معرفة هل توجد أية كائنات مرتبطة عن طريقة استخدام أسلوب ?association.nil
if @supplier.account.nil? @msg = "No account found for this supplier" end
4.2.5 متى تحفظ الكائنات؟
عند تعيين كائن إلى ارتباط has_one
، سيُحفظ ذلك الكائن بشكل تلقائي (من أجل تحديث مفتاحه الخارجي)، بالإضافة إلى ذلك، يُحفظ أي كائن أُستبدل بشكل تلقائي لأن المفتاح الخارجي سيتغير أيضا.
إذا فشلت عملية الحفظ بسبب أخطاء تحقق (validation)، فإن إعلان التعيين سيرجع false
ويُلغى التعيين نفسه.
إذا لم يُحفظ (سترجع ?new_record
قيمة false
) الكائن الأب (الذي يعلن ارتباطhas_one
)، فإن الكائنات الأبناء لن يُحفظوا أيضا، وسيُحفظون تلقائيا عند حفظ الكائن الأب.
إذا أردت تعيين كائن إلى ارتباط has_one
بدون حفظ الكائن، استخدم أسلوب association.build
.
وسنتابع في الدرس القادم شرح مرجع ارتباط has_many (الأساليب المضافة والخيارات).
المصدر:
توثيقات Ruby on Rails
تم التعديل في بواسطة zahershullar
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.