2009-06-20 13 views
6

मैं रेल से प्यार क्यों करता हूं यह है कि मुझे एसक्यूएल से नफरत है - मुझे लगता है कि यह एक असेंबली भाषा की तरह है जिसे एक्टिव रिकार्ड जैसे उच्च स्तरीय टूल के साथ छेड़छाड़ की जानी चाहिए। ऐसा लगता है कि मैंने इस दृष्टिकोण की सीमाओं को मारा है, हालांकि, और मैं एसक्यूएल के साथ अपनी गहराई से बाहर हूं।जटिल रेल क्वेरी - यूनियन? उप चुनें? क्या मैं अभी भी नाम_स्कोप का उपयोग कर सकता हूं?

मेरे पास बहुत सारे उप-रिकॉर्ड वाले जटिल मॉडल हैं। मेरे पास सेट 30-40 नाम_स्कोप भी है जो क्लाइंट से व्यवसाय तर्क लागू करता है। इन scopes सशर्त रूप से एक साथ बंधे हो जाते हैं, यही कारण है कि मेरे पास उन joins_ scopes है ताकि जुड़वां clobbered नहीं मिलता है।

मुझे उनमें से कुछ मिल गए हैं जो सही काम नहीं करते हैं, या कम से कम नहीं कि क्लाइंट उन्हें कैसे काम करना चाहता है। यहां मॉडल संरचना का एक अंदाजा विचार है, कुछ नामित क्षेत्रों (उदाहरण के लिए सभी आवश्यक नहीं) के साथ जो मेरे दृष्टिकोण को चित्रित करता है और मेरी समस्याओं का संकेत देता है। (कृपया माफ कर किसी भी वाक्यविन्यास त्रुटियों)

class Man < ActiveRecord::Base 
    has_many :wives 

    named_scope :has_wife_named  lambda { |n| { :conditions => { :wives => {:name => n}}}} 
    named_scope :has_young_wife_named lambda { |n| { :conditions => { :wives => {:name => n, :age => 0..30}}}} 
    named_scope :has_yw_named_v2  lambda { |n| { :conditions => ["wives.name = ? AND wives.age <= 30", n]}} 
    named_scope :joins_wives   :joins => :wives 

    named_scope :has_red_cat   :conditions => { :cats => {:color => 'red'}}   
    named_scope :has_cat_of_color  lambda { |c| { :conditions => { :cats => {:color => c}}}} 
    named_scope :has_7yo_cat   :conditions => { :cats => {:age => 7}} 
    named_scope :has_cat_of_age  lambda { |a| { :conditions => { :cats => {:age => a}}}} 
    named_scope :has_cat_older_than lambda { |a| { :conditions => ["cats.age > ?", a] }} 
    named_scope :has_cat_younger_than lambda { |a| { :conditions => ["cats.age < ?", a] }} 
    named_scope :has_cat_fatter_than lambda { |w| { :conditions => ["cats.weight > ?", w] } } 
    named_scope :joins_wives_cats  :joins => {:wives => :cats} 
end 

class Wife < ActiveRecord::Base 
    belongs_to :man 
    has_many :cats 
end 

class Cat < ActiveRecord::Base 
    belongs_to :wife 
end 
  1. मैं पुरुषों जिसका पत्नियों बिल्लियों कि लाल सात साल पुरानी हैं और है

    @men = Man.has_red_cat.has_7yo_cat.joins_wives_cats.scoped({:select => 'DISTINCT men'}) 
    

    और मैं भी पुरुषों जिसका पत्नियां हैं पा सकते हैं पा सकते हैं बिल्लियों जो 20 पाउंड से अधिक हैं और 6 साल से अधिक

    @men = Man.has_cat_fatter_than(20).has_cat_older_than(5).joins_wives_cats.scoped({:select => 'DISTINCT men'}) 
    

    लेकिन यह नहीं है मैं क्या चाहता हूँ। मैं उन पुरुषों को ढूंढना चाहता हूं जिनके पत्नियों में उनमें से कम से कम एक लाल बिल्ली और एक सात वर्षीय बिल्ली है, जिसे एक ही बिल्ली नहीं होने की आवश्यकता है, या उन पुरुषों को ढूंढने के लिए जिनकी पत्नियां उनमें से कम से कम एक बिल्ली को दिए गए वजन से ऊपर है और दी गई उम्र से पुरानी एक बिल्ली।
    ,

  2. मैं एस्थर

    @men = Man.has_wife_named('Esther') 
    

    नामित पत्नियों के साथ पुरुषों मैं भी एस्थर नामित पत्नियों के साथ पुरुषों पा सकते हैं पा सकते हैं (बाद उदाहरण में, उचित joins_ की उपस्थिति और DISTINCT मान लें) रुथ या एडा (मीठा!)

    @men = Man.has_wife_named(['Esther', 'Ruth', 'Ada']) 
    

    लेकिन मैं एस्तेर और रूथ नाम की पत्नियों के साथ पुरुषों को ढूंढना चाहता हूं और एडीए।

  3. हा हा, ही मजाक कर रहा है, वास्तव में, मैं की जरूरत है इस: मैं पत्नियों के साथ पुरुषों 30 एस्थर

    नामित
    @men = Man.has_young_wife_named('Esther') 
    

    @men = Man.has_young_wife_named(['Esther', 'Ruth', 'Ada']) 
    
    नामित एस्थर, रुथ या एडीए युवा पत्नियों के साथ पुरुषों को खोजने के तहत प्राप्त कर सकते हैं

    लेकिन ऊपर के रूप में मैं एस्तेर और रूथ और एडा नाम की युवा पत्नियों के साथ पुरुषों को ढूंढना चाहता हूं। सौभाग्य से, न्यूनतम इस मामले में तय किया गया है, लेकिन न्यूनतम आयु भी निर्दिष्ट करना अच्छा होगा।

  4. वहाँ एक हैश वाक्य रचना के साथ एक असमानता के लिए परीक्षण करने के लिए एक रास्ता है, या आप हमेशा :conditions => ["", n] पर वापस लौटने के लिए क्या है - has_young_wife_named और has_yw_named_v2 के बीच का अंतर ध्यान दें - मैं पहली बार बेहतर पसंद है, लेकिन सीमा केवल परिमित लिए काम करता है मान। यदि आप एक पुरानी पत्नी की तलाश में हैं, तो मुझे लगता है कि आप a..100 का उपयोग कर सकते हैं, लेकिन तब जब कोई पत्नी 101 साल की हो जाती है तो वह खोज को छोड़ देती है। (हम्म।क्या वह खाना बना सकती है? जे/के)

  5. क्या एक दायरे के भीतर एक दायरा का उपयोग करने का कोई तरीका है? मुझे :has_red_cat किसी भी तरह :has_cat_of_color का उपयोग कर सकता है, या अगर उसके माता-पिता में किसी बच्चे के रिकॉर्ड से दायरे का उपयोग करने का कोई तरीका था, तो मैं इसे प्यार करूंगा, इसलिए मैं बिल्ली से संबंधित स्कॉप्स को Wife मॉडल में डाल सकता था।

मैं वास्तव में नहीं सीधे एसक्यूएल में यह करने के लिए named_scope का उपयोग किए बिना, चाहते हैं जब तक कि वहाँ वास्तव में अच्छा कुछ और - मैं करने की आवश्यकता होगी एसक्यूएल की तरह में प्लग इन और whatnot के लिए सुझाव बहुत सराहना, या दिशा सीखते हैं। एक दोस्त ने सुझाव दिया कि यूनियन या उप-खोज यहां काम करेगी, लेकिन रेल के संदर्भ में उन पर चर्चा नहीं की जा रही है। मुझे अभी तक विचारों के बारे में कुछ भी पता नहीं है - क्या वे उपयोगी होंगे? क्या उन्हें बनाने के लिए एक रेल-खुश तरीका है?

धन्यवाद!

जैसा कि मैंने St Ives
लिए जा रहा था मैं सात पत्नियों
के साथ एक आदमी से मुलाकात की प्रत्येक पत्नी थी सात बोरियों
प्रत्येक बोरी सात बिल्लियों
था प्रत्येक बिल्ली था सात किट
किट, बिल्लियों, बोरे, पत्नियां
सेंट इव्स में कितने जा रहे थे?

+1

यह सार में एक वास्तव में दिलचस्प सवाल है। और मैं समझता हूं कि आपके मॉडल और दायरे के नाम नर्सरी कविता से व्युत्पन्न होते हैं। लेकिन यह मेरे लिए, offputting है। पत्नी: आदमी से संबंधित है? गंभीरता से? –

+0

हाँ, मैंने सोचा था कि जब मैं इसे लिख रहा था, लेकिन कविता मेरे सिर में चली गई और मैं इससे छुटकारा नहीं पा सका। –

+0

मैं एआर में नामित क्षेत्रों में यूनियन के लिए एक अच्छा तरीका खोजना चाहता हूं। मुझे पता है कि आप उन्हें स्क्लेक्लेमी में कर सकते हैं। – mikelikespie

उत्तर

2

ठीक है, मैं इस तरह के named_scope रों साथ महान परिणाम मिला है मैं उम्मीद कर रहा हूँ। इन क्षेत्रों में शामिल होने के उपयोग की आवश्यकता नहीं होती है, और वे अन्य स्टाइल में शामिल होने के साथ अच्छी तरह से खेलते हैं।

w00t!

टिप्पणी इस बात से उत्साहित है कि यह करने का यह एक प्रभावी तरीका है, या यदि कोई और 'रेल-वाई' तरीका है। एक एसक्यूएल सबक्वायरी खंड के रूप में किसी अन्य मॉडल से एक दायरा शामिल करने का कोई तरीका उपयोगी हो सकता है ...

0

आपने रेल के लिए सबसे मूल समाधान का उपयोग किया था। सीधे एसक्यूएल का एक ही प्रदर्शन होगा इसलिए इसका उपयोग करने का कोई कारण नहीं है। मैं अब सफलतापूर्वक

Member.has_cat_older_than(6).has_young_wife_named('Miriam').has_young_wife_named('Vashti') 

करते हैं और मैं क्या 'प्राप्त कर सकते हैं

named_scope :has_cat_older_than lambda { |a| { :conditions => ["men.id in (select man_id from wives where wives.id in (select wife_id from cats where age > ?))", a] } } 

और

named_scope :has_young_wife_named lambda { |n| { :conditions => ["men.id in (select man_id from wives where name = ? and age < 30)", n] } } 

:

+0

मैं और अधिक प्रदर्शन नहीं ढूंढ रहा हूं - मैं क्वेरी को ठीक से काम करने के लिए देख रहा हूं। मैं या तो जानना चाहता हूं कि रेल के भीतर मेरी क्वेरी को सही ढंग से कैसे व्यवस्थित करना है, या एसक्यूएल कैसे लिखना है जो इसे करेगा। –

2

मैंने एक नाम के नाम पर एक नाम_स्कोप के उप-चयन को पूरा करने के लिए build_finder_sql का उपयोग किया है। यह सभी के लिए नहीं हो सकता है, लेकिन इसका उपयोग करने से हम रिपोर्ट के लिए इस्तेमाल किए गए कुछ नाम-नामों को तैयार कर सकते हैं।

Man.has_cat_older_than(6).send(:construct_finder_sql,{}) 

अपनी स्क्रिप्ट/कंसोल में आज़माएं।

+0

अंततः इसे समझने में मुझे 7 महीने लगे, और यह वास्तव में वास्तव में आसान है। मुझे लगता है कि यह मेरी मूल समस्या को हल करेगा, और यह सिर्फ एक समान परेशानी का सामना करना पड़ा। समर्थक टिप: 'भेजने के लिए (:, construct_finder_sql {: चयन => 'men.id'}))' ताकि आप के साथ, उदाहरण के लिए रिकॉर्ड को बाहर एक स्ट्रिंग में एक गुंजाइश चालू करने के लिए: 'named_scope: excluding_sql, लैम्ब्डा {| एसक्यूएल | {: conditions => "men.id NOT (# {sql})"}} ' इस तरह: ' Man.complex_scope_one.exclude_sql (Man.complex_scope_two.send (: construct_finder_sql, {: select => 'पुरुष .id '}))) यह जटिल_स्कोप_ऑनो को जटिल_स्कोप_ऑन से बाहर कर देगा! धन्यवाद! –

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

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