درابزون has_many: من خلال بحث من سمات إضافية في تاريخ نموذج
-
03-07-2019 - |
سؤال
والجديدة على حد سواء روبي والقضبان ولكن أنا كتاب تعليمه حتى الآن (وهو ما يعني على ما يبدو لا شيء، هاها).
ولقد حصلت على نموذجين، حدث والعضو انضم من خلال الجدول EventUser
class User < ActiveRecord::Base
has_many :event_users
has_many :events, :through => :event_users
end
class EventUser < ActiveRecord::Base
belongs_to :event
belongs_to :user
#For clarity's sake, EventUser also has a boolean column "active", among others
end
class Event < ActiveRecord::Base
has_many :event_users
has_many :users, :through => :event_users
end
وهذا المشروع هو التقويم، والتي لا بد لي من تتبع الناس الاشتراك والخدش اسمهم لحدث معين. الرقم الأول الكثيرين للكثيرين هو نهج جيد، ولكن لا أستطيع أن أفعل شيئا من هذا القبيل:
u = User.find :first
active_events = u.events.find_by_active(true)
ولأن الأحداث لم يكن لديك فعلا أن بيانات إضافية، ونموذج EventUser لا. وبينما يمكن أن أفعله:
u = User.find :first
active_events = []
u.event_users.find_by_active(true).do |eu|
active_events << eu.event
end
ويبدو أن هذا يتعارض مع "الطريق القضبان". يمكن لأي شخص أن ينير لي، هذا وقد تم التنصت لي لهذه الليلة (هذا الصباح) منذ وقت طويل؟
المحلول
وماذا عن إضافة شيء مثل هذا في نموذج العضو الخاص بك؟
has_many :active_events, :through => :event_users,
:class_name => "Event",
:source => :event,
:conditions => ['event_users.active = ?',true]
وبعد ذلك يجب أن تكون قادرة على الحصول على أحداث نشطة لمستخدم فقط من خلال الدعوة:
User.first.active_events
نصائح أخرى
وميلان Novota لديه حل جيد - ولكن :conditions
الآن مهملة وبت :conditions => ['event_users.active = ?',true]
فقط لا يبدو القضبان جدا على أي حال. أنا أفضل شيء مثل هذا:
has_many :event_users
has_many :active_event_users, -> { where active: true }, class_name: 'EventUser'
has_many :active_events, :through => :active_event_users, class_name: 'Event', :source => :event
وبعد ذلك يجب أن يكون لا يزال قادرا على الحصول على أحداث نشطة لمستخدم فقط من خلال الدعوة:
User.first.active_events
وعلى الرغم من u.events الخاص بك لا <م> صراحة م> استدعاء الجدول user_events، لا يزال شمل هذا الجدول في SQL <م> ضمنا م> بسبب ما يلزم من صلات. لذلك، يمكنك الاستمرار في استخدام هذا الجدول في ظروف العثور على:
u.events.find(:all, :conditions => ["user_events.active = ?", true])
وبطبيعة الحال، إذا كنت تخطط لأن تفعل هذا البحث الكثير ثم يقين، وإعطائها جمعية منفصلة كما يقترح ميلان Novota، ولكن ليس هناك <م> متطلبات م> بالنسبة لك أن تفعل ذلك بهذه الطريقة
حسنا، ويجري وضع المزيد من المسؤولية في نموذج User
مما هو مطلوب فعلا، وليس هناك سبب وجيه للقيام بذلك.
ويمكننا أولا تحديد نطاق في نموذج EventUser
لأن المكان الذي ينتمي إليه فعلا، مثل:
class EventUser < ActiveRecord::Base
belongs_to :event
belongs_to :user
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
end
والآن، ويمكن للمستخدم أن يكون كل نوع من الأحداث: الأحداث النشطة فضلا عن الأحداث غير نشطة، حتى نتمكن من تحديد العلاقة في نموذج User
كما يلي:
class User < ActiveRecord::Base
has_many :active_event_users, -> { active }, class_name: "EventUser"
has_many :inactive_event_users, -> { inactive }, class_name: "EventUser"
has_many :inactive_events, through: :inactive_event_user,
class_name: "Event",
source: :event
has_many :active_events, through: :active_event_users,
class_name: "Event",
source: :event
end
وجمال في هذه التقنية هو أن وظيفة من كونها نشاطا أو حدث غير نشط ينتمي إلى EventUser
نموذج، وإذا كان في المستقبل وظيفة تحتاج إلى تعديل، يمكن تعديل إلا في مكان واحد: نموذج EventUser
، و سوف تنعكس التغييرات في كل النماذج الأخرى.