2013-03-17 9 views
11

रेल ऐप पर रूबी में मैं काम कर रहा हूं कि मैं उपयोगकर्ताओं को फाइल अपलोड करने की अनुमति देता हूं और इन फ़ाइलों को एक छोटा, यादृच्छिक अल्फान्यूमेरिक नाम देना चाहता हूं। (उदाहरण के लिए 'g7jf8' या '3bp76')। इसे करने का बेहतरीन तरीका क्या है?मैं रूबी में एक यादृच्छिक और अद्वितीय स्ट्रिंग कैसे उत्पन्न होगा?

मैं मूल फ़ाइल नाम और टाइमस्टैम्प से हैश/एन्क्रिप्टेड स्ट्रिंग उत्पन्न करने की सोच रहा हूं। फिर डेटाबेस को दोबारा जांचने के लिए पूछें कि यह अस्तित्व में नहीं है। यदि ऐसा होता है, तो दूसरा उत्पन्न करें और दोहराएं।

इस दृष्टिकोण के साथ मैं जो मुद्दा देखता हूं वह यह है कि यदि डुप्लिकेट तारों की उच्च संभावना है, तो यह डेटाबेस लोड का काफी हिस्सा जोड़ सकता है।

+1

वहाँ भी संभावित (अगर असंभव) एक ही समय में एक ही नाम जोड़ने की कोशिश कर दो अनुरोधों की दौड़ शर्त है।डेटाबेस को उस कॉलम पर एक अनूठी बाधा होनी चाहिए और आपको 'ActiveRecord :: RecordNotUnique' पकड़ने के लिए तैयार होना चाहिए। – mpartel

+0

जांचें http://stackoverflow.com/questions/5966910/generate-unique-random-string-with-letters-and-numbers-in-lower-case – sameera207

+0

क्या "यादृच्छिक" नाम का सुरक्षा उद्देश्य है? यदि नहीं, तो आपके पास और विकल्प हैं। –

उत्तर

9

मैं का उपयोग इस :)

def generate_token(column, length = 64) 
    begin 
    self[column] = SecureRandom.urlsafe_base64 length 
    end while Model.exists?(column => self[column]) 
end 

अपने मॉडल का नाम

5

रूबी के SecureRandom.hex फ़ंक्शन का उपयोग उस वैकल्पिक वर्ण के साथ करें जिसे आप उत्पन्न करना चाहते थे।

+3

इस प्रश्न के लिए मेरा पसंदीदा 'SecureRandom.urlsafe_base64' हो सकता है। –

0

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

0

यदि आप एक हेक्स या न्यूमेरिक डाइजेस्ट उत्पन्न करते हैं, तो आप संख्या को प्रतिनिधित्व करके कोड को छोटा रख सकते हैं। बेस 62:

# This is a lightweight base62 encoding for Ruby integers. 
B62CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a 

def base62_string nbr 
    b62 = '' 
    while nbr > 0 
    b62 << B62CHARS[nbr % 62] 
    nbr /= 62 
    end 
    b62.reverse 
end 

आप खिला का एक तरीका मिल सकता है यह महत्वपूर्ण है कि आप (उदाहरण फ़ाइल नामों में अपरकेस अक्षर हो नहीं करने के लिए) वर्ण का उपयोग सेट को प्रतिबंधित करने के लिए है, तो इस कोड को आसानी से अनुकूलित किया जा सकता है, बशर्ते हैं एक उपयुक्त यादृच्छिक संख्या में।

अपने फ़ाइल नाम अर्द्ध सुरक्षित होने की अपेक्षा की जाती है, तो आप भंडारण में वास्तविक नाम से बहुत अधिक संभव नाम देखते हैं कि व्यवस्था करने की जरूरत।

+0

यह कुछ अद्वितीय नहीं उत्पन्न करता है, ओपी ने यही पूछा है। एक ही 'nbr' को देखते हुए यह हर बार एक ही स्ट्रिंग को वापस कर देगा, और आपको किसी भी महत्वपूर्ण आकार की स्ट्रिंग को वापस करने के लिए हास्यास्पद रूप से बड़ी संख्या उत्तीर्ण करने की आवश्यकता है। पूर्व: '> base62_string 99 99 99 99 99 99 99 99 99 99 # =>" 1V973MbJYWoT "' –

+0

@ क्रिसब्लूम 7: सहमत है, इसे किसी संख्या में खिलाने की ज़रूरत है, जिसे मैं समझाने की व्याख्या नहीं करता हूं (लेकिन मैं आवश्यक पाठ में उल्लेख करता हूं)। रुबी में उपयुक्त आकार की यादृच्छिक संख्या उत्पन्न करना यद्यपि है: 'SecureRandom.random_number (2 ** 128) '। दृष्टिकोण अनुक्रम, हैश इत्यादि के साथ भी काम करता है। तथ्य यह है कि इसे एक छोटी स्ट्रिंग बनाने के लिए वास्तव में ओपी के लिए वांछनीय इनपुट की आवश्यकता होती है, उन्होंने एक छोटी स्ट्रिंग –

8
SecureRandom.uuid 

आपको वैश्विक स्तर पर अद्वितीय स्ट्रिंग देगा। http://en.m.wikipedia.org/wiki/Universally_unique_identifier

SecureRandom.hex 32 

एक यादृच्छिक स्ट्रिंग देंगे, लेकिन यह एल्गोरिथ्म विशिष्टता के लिए अनुकूल नहीं है है। बेशक, 32 अंकों के साथ टकराव का मौका, वास्तविक यादृच्छिकता मानते हुए, मूल रूप से सैद्धांतिक है। आप 100 वर्षों के लिए प्रति सेकंड 1 बिलियन बना सकते हैं और टकराव का केवल 50% मौका है।

-1

यह सही लगता है कि आप वास्तव में एक अद्वितीय फ़ाइल नाम की ज़रूरत है? जटिल समाधानों के बारे में क्यों न भूलें और बस Time#nsec का उपयोग करें?

t = Time.now  #=> 2007-11-17 15:18:03 +0900 
"%10.9f" % t.to_f #=> "1195280283.536151409" 
+0

के लिए कहा है यदि ऐप बड़ा और व्यस्त है, और इसमें कई स्वतंत्र सर्वर हैं , अंत में दो एक ही समय में एक फाइल को संसाधित करेंगे और टक्कर प्राप्त करेंगे। –

+0

सर्वर के नाम के साथ Concat _nanosecs_ पूरी तरह से सुनिश्चित होने के लिए। – mudasobwa

+1

उस बिंदु पर, SecureRandom.uuid मुझे लगता है कि एक आसान समाधान है। –

0

यह द्वारा Model बदलें हमेशा नए uniq 40 आकार अल्फा-न्यूमेरिक स्ट्रिंग का उत्पादन करेगा, क्योंकि यह समय स्टाम्प भी है।

पाश कर

random_token = Digest::SHA1.hexdigest([Time.now, rand(111..999)].join) 

    break random_token unless Model.exists?(column_name: random_token) 

अंत

नोट: अपने मॉडल के किसी भी मौजूदा स्तंभ करके अपने MODEL_NAME और COLUMN_NAME द्वारा मॉडल बदलें।

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

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