2015-02-05 6 views
20

एक क्वेरी वस्तु (नहीं एक ए.आर. मॉडल)ActiveRecord का उपयोग कर क्वेरी ऑब्जेक्ट में पैरामीटर से बचें?

class ComplexQuery 
    QUERY = <<-SQL 
    ... 
    SQL 

    def new(param1, param2) 
    ... 
    end 

    def execute 
    # format and interpolate parameters into QUERY 
    # pass finished SQL to `execute` or `select_all` 
    end 
end 

मैं कैसे आसानी से सभी मापदंडों से बचने कर सकते हैं को देखते हुए?

मैं तीन तकनीकों के साथ सफल रहा हूं, लेकिन कोई भी सुविधाजनक नहीं है।

  1. उपयोग raw_connection जो (मेरे लिए) PG::Conn का एक उदाहरण देता है और exec_params कहते हैं। मैं इससे संतुष्ट नहीं हूं क्योंकि exec_params को डेटा प्रकार निर्दिष्ट करने के लिए तर्कों के वर्बोज़ सेट की आवश्यकता होती है।
  2. include ActiveRecord::Sanitization मेरी क्वेरी ऑब्जेक्ट में और इसकी सुविधाजनक विधियों में से एक का उपयोग करें, जैसे replace_named_bind_variables। मैं इससे संतुष्ट नहीं हूं क्योंकि replace_named_bind_variablesprotected है और मुझे send का उपयोग करना है।
  3. इसके बजाय module लिखें। किसी कारण से, जब मैं मॉड्यूल में include ActiveRecord::Sanitization करता हूं, तो मैं इसकी संरक्षित विधियों का उपयोग करने में सक्षम हूं। मैं इससे संतुष्ट नहीं हूं क्योंकि मैं कभी-कभी इसे निष्पादित किए बिना अपनी क्वेरी ऑब्जेक्ट को तुरंत चालू करना चाहता हूं, उदा। परीक्षण के लिए।

एक class में ActiveRecord::Sanitization सहित सबसे अच्छा समाधान की तरह लगता है, लेकिन मैं कुछ गलत कर दिया जाना चाहिए क्योंकि मैं एक protected विधि का उपयोग करने में सक्षम होना चाहिए।

मैं एक समाधान है कि की तलाश में हूँ:

  1. से अधिक पैरामीटर
  2. ActiveRecord
  3. के उपभोक्ताओं द्वारा इस्तेमाल किया जा करने का इरादा है निकल जाता है एक पैरामीटर और यह प्रारूपों तदनुसार के डेटा प्रकार infers

मैं कुछ संबंधित प्रश्न ढूंढने में सक्षम था

+0

उपर्युक्त के बारे में बात की गई सभी विधियां 'ActiveRecord' मणि से कुछ का उपयोग करती हैं! एक टेबल या मॉडल के बिना ActiveRecord के साथ तर्क करना मुश्किल है। –

उत्तर

5

कच्चे पोस्टग्रेस ड्राइवर का उपयोग करके तैयार कथन बनाने का सबसे अच्छा तरीका संभवतः है। दुर्भाग्य से, ActiveRecord यह सामान्य रूप से ऐसा करने का तरीका नहीं दिखाता है। वे जल्द ही इसे जोड़ सकते हैं कि mysql2 तैयार कथन का समर्थन करता है। लेकिन इस बीच, यहां रेलवे में कच्चे PG चालक के साथ ऐसा करने का तरीका बताया गया है।

http://deveiate.org/code/pg/PG/Connection.html#method-i-prepare

conn = ActiveRecord::Base.connection.raw_connection 
conn.prepare('my_query', 'SELECT foo FROM bar WHERE baz=$1 OR baz=$2') 
result = conn.exec_prepared('my_query', ['param1', 'param2']) 

नोट प्रतीक के रूप में $ के उपयोग के एक स्थितीय पैरामीटर इंगित करने के लिए। संख्या exec_prepared पर आपके द्वारा पारित सरणी में पैरामीटर की स्थिति से मेल खाती है।

+0

यह ओपी की तलाश में सबसे नज़दीकी है। मैं एक सामान्य समाधान की तलाश में था, लेकिन ओपी ने पोस्टग्रेस्क्ल का उल्लेख किया था, इसलिए यह एक उचित जवाब है। धन्यवाद। –

+0

@WayneConrad हां, उम्मीद है कि ActiveRecord किसी भी समय आधुनिक दुनिया में चलेगा, लेकिन अभी के लिए, आप अपने पसंद के चालक में एक ही चीज़ करने में सक्षम होना चाहिए। विशेष रूप से 'mysql2' ड्राइवर ने' 0.4.0' में तैयार बयानों के लिए समर्थन जोड़ा। –

+1

'exec_params' का उपयोग करना थोड़ा आसान है और' exec_prepared' से अधिक उपयुक्त है यदि यह एक कम क्वेरी है –

2

सभी सफ़ाई तरीकों वर्ग तरीके के रूप में already included in ActiveRecord::Base और के रूप में चलाने होना चाहिए रहे हैं।

कारण यह है कि सभी sanitize_* कार्यों चालक-विशिष्ट होते हैं और connection वस्तु है, जो जाहिरा तौर पर ActiveRecord::ConnectionHandling से आ रही है पर भरोसा है।

ActiveSupport::Concern अनुबंध बलों Sanitization::ClassMethods मॉड्यूल सामग्री वर्ग/मॉड्यूल कि Sanitization शामिल की कक्षा तरीकों बनने के लिए, कि वे कैसे उपलब्ध अंदर खुले ActiveRecord::Base व्युत्पन्न वर्ग बन गया है। उन्हें सार्वजनिक नहीं किया जाता है [आईएमएचओ] क्योंकि उन्हें स्थापित कनेक्शन की आवश्यकता होती है, जो आमतौर पर वंशजों के लिए सच होती है और शायद ActiveRecord::Base के लिए कोई मामला नहीं हो सकता है।

आम तौर पर, कनेक्शन के बिना पूछा जाने वाला कोई स्पष्ट तरीका नहीं है (ई जी। ActiveRecord::Base वंश में नहीं।) पोस्टग्रेज़ के लिए उद्धरण MySQL के लिए एक से अलग है।

जोड़ने पर अप: के बाद से पूरे कार्यक्षमता पहले से ही ActiveRecord::Base में प्रस्तुत किया है एक वर्ग/मॉड्यूल में ActiveRecord::Sanitization सहित, बहुत ज्यादा नहीं समझ में आता है। जैसे ही, कोई भी वास्तविक कनेक्शन के बिना इन उद्धरण कार्यक्षमता का उपयोग करना चाहता है, वह शायद अपने उद्धरण कार्यों को लागू करने के लिए है, संबंधित ConnectionAdapter#quote पर मैपिंग।

मामला है जब कनेक्शन स्थापित किया जा माना जाता है के लिए, मैं ActiveRecord::Base करने के लिए एक आवरण मॉड्यूल prepending कि जनता के लिए संरक्षित कार्यों लपेट होगा साथ जाना होगा (इस मॉड्यूल संरक्षित कार्यों उपलब्ध हो जाएगा में।)

आशा इस मदद करता है.

+0

मुझे नहीं लगता कि #sanitize_sql ... कारण सुरक्षित हैं क्योंकि उन्हें कनेक्शन की आवश्यकता है। विधि # sanitize सार्वजनिक है, और इसके लिए एक कनेक्शन की आवश्यकता है जो स्वच्छता मॉड्यूल में अन्य वर्ग विधियों के समान है। हालांकि, एक कनेक्शन की आवश्यकता है एक मूल्यवान अंतर्दृष्टि है। –

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