ما هو الكود الافتراضي للسائبة Has_many: من خلال "إرساء" في القضبان؟
-
16-09-2019 - |
سؤال
لدي أساسي has_many: من خلال العلاقة التي هي ثنائية الاتجاه:
calendars have many calendar_calendar_events
calendars have many events through calendar_calendar_events
events have many calendar_calendar_events
events have many calendars through calendar_calendar_events
أنا أريد تعيين التقاويم إلى حدث مع الأساسي calendar_ids=
الوظيفة التي has_many: من خلال الإعدادات، ومع ذلك، أريد أن أتجاوز هذه الوظيفة لإضافة بعض السحر الإضافي. لقد ألقيت نظرة عبر مصدر القضبان ولا يمكنني العثور على رمز لهذه الوظيفة. أنا أتساءل عما إذا كان شخص ما يمكن أن يشيرني إليها. سألتجه بعد ذلك على هذا الفصل لإضافة الأشياء التي أريدها :)
المحلول
يمكنك العثور على شفرة المصدر في الملف lib/active_record/associations.rb
في الخط 1295.
def collection_accessor_methods(reflection, association_proxy_class, writer = true)
collection_reader_method(reflection, association_proxy_class)
if writer
define_method("#{reflection.name}=") do |new_value|
# Loads proxy class instance (defined in collection_reader_method) if not already loaded
association = send(reflection.name)
association.replace(new_value)
association
end
define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
ids = (new_value || []).reject { |nid| nid.blank? }
send("#{reflection.name}=", reflection.class_name.constantize.find(ids))
end
end
end
يجب عليك بالتأكيد تجنب الكتابة فوق هذه الطريقة لإضافة أشياء سحرية. القضبان بالفعل "الكثير من السحر" في بعض الأحيان. أود أن أقترح إنشاء سمة افتراضية مع جميع المنطق المخصص لعدة أسباب:
- قد تعتمد بعض أساليب القضبان الأخرى على التنفيذ الافتراضي
- أنت تعتمد على واجهة برمجة تطبيقية محددة قد تتغير في إصدارات Activerecord المستقبلية
نصائح أخرى
بعد القليل من مطاردة وجدت ذلك:
http://apidock.com/rains/activerecord/associations/classmethods/collection_accessor_methods.
لم يكن يبدو وكأنه ما اعتقدت أنه سيظهر، ولهذا السبب فقد فاتني ذلك. انتهى بي الأمر إلى تجاوز التقويمات = الطريقة بدلا من التقويم = الطريقة وكل شيء يعمل بشكل جيد.
استجابة للإجابة أعلاه، استخدمت Alias_method_chain لتجاوز STERTER الافتراضي وإضافة ميزة التشغيل الخاصة بي. يعمل بشكل جيد للغاية، رغم أنني لست متأكدا من السبب في أن علي إرسال طريقة تشغيل الطريقة بدلا من استخدامها بشكل طبيعي. لا يبدو أنه يعمل على الرغم من أن هذا سيفعل :)
def calendars_with_primary_calendar=(new_calendars)
new_calendars << calendar unless new_record?
send('calendars_without_primary_calendar=', new_calendars) # Not sure why we have to call it this way
end
alias_method_chain :calendars=, :primary_calendar