2015-01-06 3 views
5

साथ शामिल रहा है निम्नलिखित मॉडलसक्रिय रिकॉर्ड एसटीआई

class Event < ActiveRecord::Base 
    has_many :attendances 

class Attendance < ActiveRecord::Base 
belongs_to :user 

class Student < User 
    has_one :student_detail 

class StudentDetail < ActiveRecord::Base 
    belongs_to :school 

class Staff < User 
    has_one :staff_detail 

class StaffDetail < ActiveRecord::Base 

StudentDetail और StaffDetails में अतिरिक्त जानकारी है, मैं यह सब एक एसटीआई उपयोगकर्ता तालिका में होने से बचाने के कोशिश कर रहा हूँ की वजह से कुछ इसी तरह के साथ काम करने के लिए है तालिका पैटर्न प्रति ठोस वर्ग

मैं यह आसानी से पर्याप्त

Event.includes(:attendances => :user).where(...) 

कर सकते हैं लेकिन मैं एक होना चाहता हूँ उपयोगकर्ता प्रकार उदा।

Event.includes(attendances: {:user => :student_details }) 

यह उपयोगकर्ताओं में से कुछ के रूप में असफल हो जायेगी स्टाफ वस्तुओं रहे हैं।

मुझे पता है रेल बॉक्स से बाहर इस का समर्थन नहीं करेंगे, लेकिन किसी को भी किसी भी चाल इस काम करने के लिए प्राप्त करने के लिए

सबसे अच्छा समाधान अभी छात्र और स्टाफ यानी

को उपस्थिति पर उपयोगकर्ता विभाजित किया गया
class Attendance < ActiveRecord::Base 
    belongs_to :student, -> {includes(:staff_detail) } 
    belongs_to :staff, -> {includes(:student_detail) } 
    #belong_to :user 

जो आदर्श नहीं है। किसी के पास कोई सुझाव है? इसे हल करने का तरीका।

उत्तर

6

सबसे आसान तरीका है कि उपयोगकर्ता को has_one एसोसिएशन को नीचे ले जाएं। चूंकि केवल Staff रिकॉर्ड staff_details होंगे, इसलिए प्रीलोडिंग केवल काम करेगी।

class User < ActiveRecord::Base 
    has_one :staff_detail 
    has_one :student_detail 
end 

class Staff < User; end 
class Student < User; end 

हालांकि यह आदर्श नहीं है। आगे प्रीलोडिंग को कस्टमाइज़ करने के लिए, आप रेल में Preloader कक्षा का उपयोग कर सकते हैं। सबसे पहले, सभी रिकॉर्ड के बिना किसी भी शामिल लोड करते हैं, तो उन पर पुनरावृति और संगठनों की जरूरत प्रीलोड:

events = Event.includes(:attendances => :user) 
users = events.users.flatten 
users.group_by(&:class).each do |klass, records| 
    associations = { 
    Staff: [:staff_detail], 
    Student: [:student_detail] 
    }.fetch(klass, []) 

    ActiveRecord::Associations::Preloader.new(records, associations).run 
end 

ध्यान दें कि यह एपीआई changed in Rails 4। संस्करण 3 और इससे पहले, आपने अभी preload_associations विधि का उपयोग किया था।

कुछ समय पहले मैंने blog post about this same problem लिखा था जिसमें कुछ अन्य साफ-सुथरे चाल शामिल हैं (जैसे कि आपको सही व्यवहार मिलता है)।

+2

वाक्य रचना फिर से बदल गया है, रेल 4.1 मेरा मानना ​​है कि के लिए कर सकते हैं। नया वाक्यविन्यास 'ActiveRecord :: संघ :: Preloader.new.preload (रिकॉर्ड, एसोसिएशन) 'है।विवरण के लिए [प्रतिबद्ध] देखें (https://github.com/rails/rails/commit/6e5a2cb9519aab568ea0cfea2f42364de8ccf655)। – Leito

2

default_scope के रूप में एसटीआई मॉडल पर includes डालने के बारे में कैसे?

class Event < ActiveRecord::Base 
    has_many :attendances 

class Attendance < ActiveRecord::Base 
belongs_to :user 

class Student < User 
    has_one :student_detail 
    default_scope includes(:student_detail) 

class StudentDetail < ActiveRecord::Base 
    belongs_to :school 

class Staff < User 
    has_one :staff_detail 
    default_scope includes(:staff_detail) 

class StaffDetail < ActiveRecord::Base 

तो मैं इस बारे में सोच:

Event.includes(:attendances => :user).where(...) 

चाहिए दोनों छात्रों और स्टाफ के लिए उत्सुक लोड।

1

आप अपने जीवन को थोड़ा आसान बनाने के लिए नामित क्षेत्रों का उपयोग कर सकते हैं।

class Event < ActiveRecord::Base 
    has_many :attendances 
    scope :for_students, -> { includes(:attendances => { :users => :student_detail }).where('users.type = ?', 'Student') } 
    scope :for_staff, -> { includes(:attendances => { :users => :staff_detail }).where('users.type = ?', 'Staff') } 
end 

तो फिर तुम सिर्फ Event.for_students

संबंधित मुद्दे