2010-12-02 10 views
5

मैं इससे थोड़ा परेशान हूं।रूबी रैंड() चर स्वीकार नहीं कर सकते हैं?

आरओआर प्रोजेक्ट में मेरा अंतिम लक्ष्य मेरे डेटाबेस से एक यादृच्छिक प्रोफ़ाइल को पकड़ना है।

मैं सोच रहा था कुछ है जैसे कि यह होगा:

@profile = Profile.find_by_user_id(rand(User.count)) 

यह एक त्रुटि क्योंकि user_id 0 मौजूद नहीं है फेंक रखा है, इसलिए मैं इसे से बाहर भागों बस की जाँच करने के लिए क्या हो रहा है खींच लिया:

@r = rand(User.count) 

<%= @r %> 

यह हर बार 0 देता है। तो क्या चल रहा है? मैंने इसका परीक्षण करने के लिए 5 नकली उपयोगकर्ता और 5 संबंधित प्रोफाइल पंजीकृत किए हैं।

अगर मैं Profile.find_by_user_id(rand(User.count)) लेने के लिए और के रूप में

Profile.find_by_user_id(3) 

यह सिर्फ ठीक काम करता है यह फिर से लिखने।

User.count भी काम कर रहा है। तो मुझे लगता है कि rand() एक स्थिर पूर्णांक के अलावा इनपुट नहीं ले सकता है।

क्या मैं सही हूँ? क्या चल रहा है?

+1

रैंड (User.count) मेरे लिए काम करता है। – drewrobb

+0

वास्तव में? ठीक हम्म मुझे देखना होगा कि क्या हो रहा है। शायद मुझे कुछ महत्वपूर्ण याद आ रही है। – Elxx

+0

एंड्रयू संपादित करने के लिए धन्यवाद। अपने स्वयं के प्रश्न को फिर से पढ़ना मुझे कभी-कभी उलझन में डाल देता है = डी – Elxx

उत्तर

9

प्रयास करें:

Profile.first(:offset => rand(Profile.count)) 

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

इसके बजाय, यदि आप रिकॉर्ड्स की संख्या गिनते हैं, तो यादृच्छिक रूप से तालिका में कुछ ऑफसेट पर जाएं, आप गायब आईडी होने की संभावना को कम कर देंगे, और केवल मौजूदा रिकॉर्ड पर उतरेंगे।

ऑप्स से निम्न उदाहरण है जब तक कि डेटाबेस की अखंडता को बहुत ध्यान से देखा है सवाल कुछ समस्याएं आ सकता है:

profile = Profile.find_by_user_id(rand(User.count)) 

समस्या है, वहाँ के लिए उपयोगकर्ता तालिका सिंक्रनाइज़ेशन से बाहर होने के लिए एक संभावना है प्रोफाइल टेबल के साथ, उन्हें विभिन्न रिकॉर्ड की अनुमति मिलती है। उदाहरण के लिए, यदि User.count 3 था और प्रोफाइल में दो रिकॉर्ड थे तो असफल लुकअप के लिए संभावित अपवाद है।

+0

बिल्कुल सही। बहुत अच्छी तरह से काम करता है। मैंने इसे सबसे अच्छा जवाब के रूप में चुना क्योंकि यह रैंक/RANDOM =) – Elxx

+1

धन्यवाद डेटाबेस विशिष्ट कार्यों को साइड करता है। हां, मैंने जानबूझकर पोर्टेबल रखने के लिए डीबी विनिर्देशों से परहेज किया। इसे पूरी तरह से डीबीएम में चलाने के लिए लिखा जा सकता है लेकिन यह क्वेरी को किसी विशेष डेटाबेस से जोड़ देगा। जैसा कि, इसे डेटाबेस में दो कॉल करना है, लेकिन वे बहुत तेज़ हैं और इसमें कोई खोज शामिल नहीं होनी चाहिए। –

+0

हमेशा तेज होना नहीं है। उदाहरण के लिए, पोस्टग्रेस धीमी COUNT (*) क्वेरी के लिए कुख्यात है। –

-3

का पता लगाकर आईडी में रेल शायद रेल Conventions Over Configuration समझदार चूक जो सिर्फ लोगों पर सहमत नियमों की वजह से है निरर्थक

@profile = Profile.find_by_user_id(rand(User.count)) 
#This is redudent, all you need to code is: 
@profile = Profile.find(rand(User.count)) #default for Rails is ID 

त्रुटि 0 के आधार पर संदेश है।

और रेल का उपयोग करते समय उपयोगकर्ता को 0 के रूप में रखने का कोई कारण नहीं है, यह हमेशा 1 से शुरू होता है जिसे मैं डीएचएच को अधिक पठनीय होने की कोशिश करता हूं।

+0

जहां तक ​​मैं कह सकता हूं उसके प्रश्न के साथ इसका कोई लेना-देना नहीं है। मैं सहमत हूं कि Profile.find (rand_int) प्रोफाइल.find_by_user_id (rand_it) से अधिक समझदार है, लेकिन find_by_user_id किसी भी वास्तविक अर्थ में "अनावश्यक" नहीं है। मुझे यह भी पता नहीं है कि आपकी बाकी पोस्ट किस बारे में बात कर रही है। – bnaul

+0

क्षमा करें मैं पोस्ट को और अधिक समझने की कोशिश करूंगा। मैं Profile.find_by_user_id को कॉल करता हूं क्योंकि 2 कॉलम, आईडी और user_id हैं। मैं user_id कॉलम के आधार पर पंक्ति का चयन करना चाहता हूं। तो, यह बहुत जरूरी है। – Elxx

4

मुझे यकीन नहीं है कि क्यों रैंड (i) काम नहीं कर रहा है जैसा कि आप उम्मीद करते हैं (यह मेरे लिए ठीक काम करता है), लेकिन यह यादृच्छिक प्रोफ़ाइल खोजने के लिए एक अच्छा तरीका नहीं है; यदि कोई प्रोफ़ाइल कभी हटा दी जाती है, या प्रोफ़ाइल के बिना कोई उपयोगकर्ता हैं, तो यह असफल हो जाएगा।

मुझे नहीं लगता कि ActiveRecord का उपयोग कर रेल में ऐसा करने का एक प्रभावी तरीका है। उपयोगकर्ताओं की एक छोटी संख्या के लिए, तुम सिर्फ Profile.find_all (कर सकता है) और उस सरणी से एक यादृच्छिक प्रोफ़ाइल का चयन करें, लेकिन आप शायद बेहतर होगा की तरह

@profile = Profile.find_by_sql("SELECT * FROM profiles ORDER BY RAND() LIMIT 1").first 

कुछ कर रही StackOverflow पर कई अन्य सवाल कर रहे हैं एसक्यूएल में यादृच्छिक रिकॉर्ड का चयन कैसे करें; मैं कहूंगा कि यह सबसे आसान है, लेकिन यदि आप दक्षता के बारे में चिंतित हैं तो एक नज़र डालें और देखें कि क्या एक और कार्यान्वयन आपको बेहतर पसंद है।

संपादित करें: find_by_sql एक सरणी देता है, इसलिए आपको एक प्रोफ़ाइल प्राप्त करने की आवश्यकता है।

+0

मैं इसे आज़माउंगा। यह कभी मेरे लिए कभी नहीं हुआ कि लोग अपनी प्रोफाइल को हटाते हुए गड़बड़ कर देंगे .... मुझे टेस्ट के मामलों को लिखना शुरू करना होगा। – Elxx

+0

जिस तरह से वह यह कर रहा है वह सबसे अच्छा है (रुबी में यादृच्छिक संख्या उत्पन्न करना और फिर इसे 'आईडी' कॉलम में खोजना) - वास्तव में वह पंक्ति ढूंढने में लगातार समय लगता है। इसे अपने तरीके से करने के लिए यादृच्छिक संख्याएं असाइन करने के लिए एक पूर्ण तालिका स्कैन की आवश्यकता होती है, और ओ (एन लॉग एन) सॉर्ट की आवश्यकता होती है, इससे पहले कि वह एक पंक्ति को वापस कर सके। –

+2

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

1

मैं रेल में एक यादृच्छिक रिकॉर्ड प्राप्त करना चाहते हैं, मैं कुछ इस तरह जाना:

@profile = Profile.first(:order => "RAND()") 

यह आमतौर पर काम करता है, लेकिन मैं क्या पढ़ा है पहले से, रैंड() आदेश MySQL के लिए विशिष्ट है या कम से कम डेटाबेस स्वतंत्र नहीं है। अन्य लोग रैंडम() का उपयोग कर सकते हैं।

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