11

में उपनाम नाम() और जुड़ने() में उपनाम नाम देने के लिए कैसे मैं उदाहरण के लिए उपनाम नाम दे सकता हूं includes()? निम्नलिखित दिया जाता है:रेल 4 - सक्रिय रिकॉर्ड पूछताछ

  • उपयोगकर्ता: सक्रिय रिकॉर्ड मॉडल
  • छात्र: सक्रिय रिकॉर्ड मॉडल, उपयोगकर्ता से विरासत (एसटीआई)
  • शिक्षक: सक्रिय रिकॉर्ड मॉडल, उपयोगकर्ता से विरासत (एसटीआई)
  • परियोजना : सक्रिय रिकॉर्ड मॉडल

यहाँ कुछ उदाहरण:

पहला मामला (अधिक एसटीआई संघों)

Project.all.includes(:students, :teachers).order('teachers_projects.name ASC') # order on teachers 
Project.all.includes(:students, :teachers).order('users.name ASC') # order on students 

रेल एसक्यूएल में :teachers के लिए नाम teachers_projects उर्फ ​​स्वचालित रूप से उपयोग करता है। मैं इसे कैसे ओवरराइट कर सकता हूं, ताकि मैं SQL में teachers_projects के बजाय उपनाम नाम teachers का उपयोग कर सकूं? :students उपनाम का नाम users मिलता है।

इस उदाहरण में विफल रहता है:

Project.all.includes(:students, :teachers).order('teachers.name ASC') 
Project.all.includes(:students, :teachers).order('students.name ASC') 
Project.all.includes(:students, :teachers).order('students_projects.name ASC') 

दूसरे मामले (एक एसटीआई संघ)

अगर मैं विधि includes() में केवल :students (:teachers के बिना) का उपयोग करें, रेल एसटीआई का नाम उर्फ ​​का उपयोग करता है :students:

के लिए बेस क्लास नाम users (बिना _projects संलग्न)
Project.all.includes(:students).order('users.name ASC') # order on students 

इस उदाहरण में विफल रहता है:

Project.all.includes(:students).order('students.name ASC') 
Project.all.includes(:students).order('students_projects.name ASC') 

प्रश्न

की तरह कुछ मौजूद सकता है:

Project.all.includes(:students).alias(students: :my_alias) 

रेल ALIAS ट्रैकर

https://github.com/rails/rails/blob/v4.2.0/activerecord/lib/active_record/associations/alias_tracker.rb#L59

परीक्षण एपीपी

https://gist.github.com/phlegx/add77d24ebc57f211e8b

https://github.com/phlegx/rails_query_alias_names

+0

क्या आपने Project.joins (: शिक्षकों) जैसी कुछ कोशिश की है। कहीं ...... – Leon

+0

यदि आपको उत्तर मिलता है, तो कृपया मुझे _notify_ करें, ताकि मैं जवाब भी देख सकूं। –

+0

क्या आप मॉडल परिभाषाओं, माइग्रेशन और कुछ डेटा दिखाने के लिए एक गिस्ट भी दे सकते हैं .. ताकि मैं स्थापित कर सकूं, और करने का प्रयास कर सकूं? –

उत्तर

1

मैं इस मुद्दे के लिए एक और तरीका अपनाने जा रहा हूँ: बजाय एक साथ आपके चयन पर उर्फ ​​नाम पर नियंत्रण की कोशिश की .alias विधि, मैं रेल/एरल को संभालने दूंगा और जब भी किसी दायरे में इसकी आवश्यकता हो, तो सही तालिका नाम (उपनाम या नहीं) देखें।

इस मॉडल को अपने मॉडल में जोड़ें, ताकि आप यह जानने के लिए एक दायरे से कॉल कर सकें कि JOIN के भीतर स्कोप का उपयोग किया जा रहा है जिसमें तालिका का नाम अलियाड (एकाधिक तालिका एक ही तालिका में शामिल होता है), या यदि दूसरी तरफ तालिका के नाम के लिए दायरे में कोई उपनाम नहीं है।

def self.current_table_name 
    current_table = current_scope.arel.source.left 

    case current_table 
    when Arel::Table 
    current_table.name 
    when Arel::Nodes::TableAlias 
    current_table.right 
    else 
    fail 
    end 
end 

इस आधार वस्तु के रूप में current_scope का उपयोग करता अरेल तालिका देखने के लिए। मैं source पर उस ऑब्जेक्ट पर Arel::SelectManager प्राप्त करने के लिए कॉल कर रहा हूं जो बदले में आपको #left पर वर्तमान तालिका देगा। वहां दो विकल्प हैं: या तो आपके पास Arel::Table (कोई उपनाम नहीं है, तालिका का नाम #name पर है) या आपके #right पर उपनाम के साथ Arel::Nodes::TableAlias है।

अब आप केवल उपयोग करने के लिए है कि अपने order बयान (untested) पर की जरूरत है:

Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") 
Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") 
Project.all.includes(:students, :teachers).order("#{current_table_name}.name ASC") 

संबंधित प्रश्न:

+0

मैंने आपके द्वारा संदर्भित प्रश्नों में से एक में एक उत्तर दिया। आप इसे थोड़ा सा सरल बना सकते हैं। 'current_scope.table'' current_scope.arel.source.left' जैसा है (शायद रेल में नहीं <4.2.2?)। और यदि आप '' एरियल सिंटैक्स 'का उपयोग करते हैं, तो आपको नंगे टेबल नाम प्राप्त करने की आवश्यकता नहीं है। जैसे इसे इस तरह प्रयोग करें: 'at = current_scope.table', और फिर' at: :_c_cumnumnname] .asc' और 'Arel' आपके लिए सब कुछ करें। (शायद आपको एक '.to_sql' जोड़ना है, लेकिन मुझे लगता है कि रेल इसे आपके लिए संभाल लेंगे) – 244an

2

अरेल वास्तव में एक उपनाम विधि है।

student_alias = Student.arel_table.alias(:my_student_table_alias) 

चेतावनी: इसके लिए आपको और भी हस्तनिर्मित एरियल का उपयोग करने और मैन्युअल रूप से शामिल होने की आवश्यकता होगी। और यदि आप उनका उपयोग नहीं कर रहे हैं तो एरियल में शामिल होने से थोड़ा जटिल हो सकता है।

student_alias_join = student_alias.create_on(
    Project.arel_table[:primary_key].eq(student_alias[:project_id]) 
) 

Project.joins(
    Project.arel_table.create_join(
    student_alias, student_alias_join, Arel::Nodes::OuterJoin 
) 
).order(...) 

ऐसा कुछ ऐसा करना चाहिए। निश्चित रूप से इसे :my_student_table_alias के साथ कुछ क्लास विधि में डालने के रूप में पैरामीटर इसे अधिक साफ और पुन: प्रयोज्य बना देगा क्योंकि यह नियंत्रक में थोड़ा गन्दा दिखाई देगा।

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