2011-08-22 7 views
16

क्या रेल विधि find_by_sql में एसक्यूएल को स्वच्छ करने का कोई तरीका है?रेल, find_by_sql में SQL को sanitize कैसे करें

मैं इस समाधान की कोशिश की है: Ruby on Rails: How to sanitize a string for SQL when not using find?

लेकिन यह

Model.execute_sql("Update users set active = 0 where id = 2") 

यह एक त्रुटि फेंकता में विफल रहता है, लेकिन एसक्यूएल कोड के निष्पादित होने और आईडी 2 के साथ उपयोगकर्ता अब एक विकलांग खाता है।

सरल find_by_sql भी काम नहीं करता:

Model.find_by_sql("UPDATE user set active = 0 where id = 1") 
# => code executed, user with id 1 have now ban 

संपादित करें:

खैर मेरे मुवक्किल (एसक्यूएल द्वारा चुनें) कुछ जटिल क्वेरी बनाने के लिए है कि समारोह बनाने के लिए व्यवस्थापक पैनल में अनुरोध (मिलती है, विशेष परिस्थितियों आदि)। तो मैं वास्तव में find_by_sql खोजना चाहता हूँ।

दूसरा संपादित करें:

मैं प्राप्त करने के लिए कि 'बुराई' SQL कोड निष्पादित नहीं किया जाएगा चाहते हैं।

व्यवस्थापक पैनल में आप क्वेरी टाइप कर सकते हैं ->Update users set admin = true where id = 232 और मैं किसी भी अद्यतन/DROP/ALTER SQL कमांड को अवरुद्ध करना चाहता हूं। बस जानना चाहते हैं, कि यहां आप केवल चयन निष्पादित कर सकते हैं।

कुछ प्रयासों के बाद मैंने निष्कर्ष निकाला कि sanitize_sql_array दुर्भाग्य से ऐसा नहीं करता है।

क्या रेल में ऐसा करने का कोई तरीका है ??

भ्रम के लिए खेद है ..

उत्तर

13

इस प्रयास करें:

connect = ActiveRecord::Base.connection(); 
connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string")) 

आप इसे चर में बचाने के लिए और अपने उद्देश्यों के लिए उपयोग कर सकते हैं।

+0

परिणाम मिला: 'संरक्षित विधि 'sanitize_sql_array' ActiveRecord :: बेस के लिए कहा जाता है: Class' –

+1

मैंने अपनी पोस्ट अपडेट की है। मुझे उम्मीद है कि यह आपको – bor1s

+0

में मदद करेगा .. या आप इसका उपयोग कर सकते हैं: 'ActiveRecord :: Base.send (: sanitize_sql_array, "आपकी स्ट्रिंग") ' – bor1s

9

मैंने इसके लिए एक छोटा स्निपेट बनाया है जिसे आप प्रारंभकर्ताओं में डाल सकते हैं।

class ActiveRecord::Base 
    def self.escape_sql(array) 
    self.send(:sanitize_sql_array, array) 
    end 
end 

अभी आप इस के साथ आपकी क्वेरी से बचने कर सकते हैं:

query = User.escape_sql(["Update users set active = ? where id = ?", true, params[:id]]) 

और आप क्वेरी किसी भी तरह से आप की तरह कॉल कर सकते हैं:

users = User.find_by_sql(query) 
+2

यह काम करेगा, लेकिन केवल एक सिर ऊपर , आपको "भेजने" की आवश्यकता नहीं होगी। जब कॉलर एक ही कक्षा है तो रिसीवर द्वारा संरक्षित विधि को कॉल करने की अनुमति है। यही है, आपको केवल विधि परिभाषा की आवश्यकता होगी: "def self.escape_sql (obj); sanitize_sql_array obj; अंत;" (एसओ टिप्पणियों के बाद से अर्धविराम रिटर्न लाइनों की अनुमति देता है) –

+0

[मुझे बंदर पैचिंग के विकल्प के बारे में यह प्रासंगिक पाया गया है) (https://stackoverflow.com/a/2329394/673826) – mlt

+0

अतिरिक्त और उदाहरण देने के लिए धन्यवाद इसका उपयोग कैसे करें। –

8

थोड़ा अधिक सामान्य उद्देश्य:

class ActiveRecord::Base 
    def self.escape_sql(clause, *rest) 
    self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest)) 
    end 
end 

यह आपको देता है इसे कॉल करें जैसे आप एक खंड में टाइप करेंगे, अतिरिक्त ब्रैकेट के बिना, और सरणी शैली का उपयोग कर रहे हैं? या हैश-शैली इंटरपोलेशंस।

+0

धन्यवाद, यह पूरी तरह से काम किया। बस यह जोड़ना कि यह प्रारंभकर्ता में जाता है। – KPheasey

1

हालांकि यह उदाहरण INSERT क्वेरी के लिए है, कोई भी अद्यतन क्वेरी के लिए समान दृष्टिकोण का उपयोग कर सकता है।कच्चे एसक्यूएल थोक डालने:

users_places = [] 
users_values = [] 
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S') 
params[:users].each do |user| 
    users_places << "(?,?,?,?)" # Append to array 
    users_values << user[:name] << user[:punch_line] << timestamp << timestamp 
end 

bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values 
begin 
    sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr) 
    ActiveRecord::Base.connection.execute(sql) 
rescue 
    "something went wrong with the bulk insert sql query" 
end 

यहाँ reference to sanitize_sql_array method in ActiveRecord::Base यह तार में एकल उद्धरण से बचने के द्वारा उचित क्वेरी स्ट्रिंग उत्पन्न करता है। उदाहरण के लिए पंच_लाइन "उन्हें आपको नीचे जाने न दें" बन जाएंगे "उन्हें आपको नीचे जाने दें"।

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