بالنظر إلى مجموعة من كائنات ActiveRecord، هل يمكنني بسهولة جمع علاقاتها من خلال استدعاء الأسلوب؟

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

سؤال

لنفترض أن لدي الكود التالي:

@sites = Site.find(session[:sites]) # will be an array of Site ids
@languages = Language.for_sites(@sites)

for_sites هو نطاق مسمى في نموذج اللغة الذي يُرجع اللغات المرتبطة بتلك المواقع، وترتبط اللغات بالمواقع التي تستخدم has_many من خلال.الهدف هو أن يكون لدى @languages ​​مجموعة متميزة من اللغات المرتبطة بالمواقع.

بدلاً من استدعاء كائن اللغة في السطر الثاني، أود أن أقول ذلك بشكل مثالي

@sites.languages

وقد عادت لي نفس القائمة.هل هناك أي طريقة للقيام بذلك بشكل نظيف في Rails 2.1 (أو الحافة)؟أعلم أن الارتباطات والنطاقات المسماة يمكنها توسيع كائن المصفوفة ليحتوي على سمات، ولكن ما لم أفتقد شيئًا لا ينطبق هنا.سيكون موضع ترحيب أي مكونات إضافية تقوم بذلك، وليس من الضروري أن تكون أساسية.

هل كانت مفيدة؟

المحلول

يمكنك توسيع المصفوفة التي تم إرجاعها بواسطة Site.find.

class Site
  def find(*args)
    result = super
    result.extend LanguageAggregator if Array === result
    result
  end
end

module LanguageAggregator
  def languages
    Language.find(:all, :conditions => [ 'id in (?)', self.collect { |site| site.id } ])
  end
end

نصائح أخرى

لماذا لا تستخدم name_scopes لكليهما؟

class Site
  named_scope :sites, lambda{|ids| :conditions => "id in (#{ids.join(',')})"}
  named_scope :languages, :include => :languages ... (whatever your named scope does)
end

يتصل:

Site.sites(session[:sites]).languages

أو، إذا كنت تريد استعادة كائنات اللغة

Site.sites(session[:sites]).languages.collect{|site| site.languages}.flatten

يمكنك أيضًا القيام بذلك مباشرةً على كائن اللغة.أنا أستخدم ‎:joins لأن Rails 2.1 ينقسم و:include إلى استعلامين مما يعني أنه لا يمكننا استخدام المواقع في :conditions

class Language
  named_scope :for_sites, lambda{|site_ids| :joins => 'inner join sites on languages.site_id = sites.id' :conditions => "sites.id in (#{site_ids.join(',')})"}
end

يتصل:

Language.for_sites(session[:sites])

في كلا المثالين افترضت أن session[:sites] يتم التحكم فيها بالكامل بواسطتك ولا تخضع لحقن SQL.إذا لم يكن الأمر كذلك، فتأكد من التعامل مع تنظيف بطاقات الهوية

متغير المثيل الخاص بك @sites هو كائن Array وليس Site، لذلك لا أعتقد أنه يمكن استخدام name_scope.يمكنك فتح فئة Array لتحقيق هذا التأثير من خلال (yikes)

class Array

  def languages
    ...
  end

end

إذا أضفت أ has_many أو has_and_belongs_to_many ربط اللغات بالمواقع، ثم يمكنك استخدام التضمين والقيام بشيء مثل هذا:

Site.find( :all, :conditions =>{:id => session[:sites]}, :include => :languages )

يمكنك إنشاء نطاق مسمى للقيام بالأمر :id => session[:sites]، على سبيل المثال:

class Site
  named_scope :for_ids, lambda{ |x| {:conditions => {:id => x }
end

ومن ثم القيام به

Site.for_ids(session[:sites]).find(:all, :include => :languages)

نأمل أن يعطيك هذا بعض الأفكار

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