درابزون has_many: من خلال بحث من سمات إضافية في تاريخ نموذج

StackOverflow https://stackoverflow.com/questions/408872

سؤال

والجديدة على حد سواء روبي والقضبان ولكن أنا كتاب تعليمه حتى الآن (وهو ما يعني على ما يبدو لا شيء، هاها).

ولقد حصلت على نموذجين، حدث والعضو انضم من خلال الجدول 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، و سوف تنعكس التغييرات في كل النماذج الأخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top