5

मेरे पास विशेषताओं वाले फिल्मों का डेटाबेस है। मैं उन फिल्मों के एक प्रश्नोत्तरी बैच को यादृच्छिक क्रम में पेजिनेशन के साथ टेम्पलेट में वापस करना चाहता हूं। मैं will_paginate का उपयोग कर रहा हूँ। मैंने कोशिश की है:रेल 3, will_paginate, यादृच्छिक, दोहराव रिकॉर्ड, पोस्टग्रेर्स, सेटसीड विफलता

## MoviesController 

movies = Movie.get_movies(query_string) # a method in Movie model that takes in 
              # a query_string and fetches movies 
              # with user-set params 

@movies = movies.order('random()').page(params[:page]).per_page(16) 

यह अच्छी तरह से काम करता है, को छोड़कर फिल्में पृष्ठ दर पृष्ठ दोहराया जाता है। इस समस्या के समाधान here और here पोस्ट किए गए हैं। वे लिंक बताते हैं कि, क्योंकि यादृच्छिक() बीज पृष्ठ से पृष्ठ पर रीसेट किया गया है, कोई स्थिरता नहीं है और OFFSET बेकार प्रदान किया जाता है। वे MySQL उपयोगकर्ताओं के लिए बहुत अच्छे समाधान प्रदान करते हैं, क्योंकि इसकी रैंड (एन) फ़ंक्शन बीज n लेता है। पोस्टग्रेस, हालांकि, ऐसा नहीं करता है। आप setseed (एन) में घोषित करने के लिए आदेश में यादृच्छिक() जारी करने से पहले का चयन करें है।

@movies = movies.select('setseed(.5)').order('random()').page(params[:page]).per_page(16) 

मजे की बात है, कि लौट आए मूवी बिल्कुल नहीं विशेषताओं के साथ वस्तुओं:

तो मैं postgres तरह से बीज स्थापित करने के लिए कोशिश की। निम्नलिखित टेम्पलेट से उठाया गया था:

ActiveModel :: MissingAttributeError फिल्म # कार्रवाई

में लापता विशेषता: some_movie_attribute

मैं इस डिबग और, एक बार ढेर पर पहुंच गया action_controller/धातु, @movies निहित:

[#<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >]

मूवी ऑब्जेक्ट्स की संख्या (18) क्वेरी से लौटाई गई फिल्मों की संख्या से मेल खाती है। जैसा कि ऊपर से बाहर रखी

@movies = movies.select('setseed(.5)').page(params[:page]).per_page(16) 

यह लौटे ही गैर विशेषता मूवी वस्तुओं:

मैं भी देखने के लिए अगर setseed (एन) यादृच्छिक क्रम विधि को निकाल कर समस्या थी निम्नलिखित की कोशिश की। तो ऐसा लगता है कि सेटसीड (एन) वास्तव में मुद्दा है।

मैं समाधान के एक जोड़े की कोशिश की, जैसे:

# MoviesController 

movies = Movie.get_movies(query_string) 
shuf_movs = movies.shuffle ## effectively turns shuf_movs into an array 

@movies = shuf_movs.paginate(:page => params[:page], :per_page => 16) 

कि भी दोहरा फिल्मों के साथ पृष्ठों लौट आए। मैंने सोचा था कि ऐसा इसलिए था क्योंकि पेजिनेशन को ऑब्जेक्ट्स को द्वारा ऑर्डर करने की आवश्यकता थी, और आप ऐरे # शफल में बीज सेट नहीं कर सकते। तो मैंने अपना खुद का यादृच्छिकरण कोड लिखने की कोशिश की जो अस्थायी रूप से मूवी ऑब्जेक्ट्स में ऑर्डर करने के लिए एक आईडी संग्रहीत करेगा। (कृपया मैला कोड क्षमा करें):

# Movie model 

attr_accessor :rand_id 

# MoviesController 

movies = get_movies(query_string) 
movies_count = movies.count 
r = Random.new 
nums = [] 
rand_movs = [] 
id = 1 
while nums.count != movies_count 
    num = r.rand(0..movies_count - 1) 
    if !(nums.include?(num)) 
    movie = movies[num] 
    movie.rand_id = id 
    rand_movs << movie 
    nums  << num 
    id += 1 
    end 
end 

@movies = rand_movs.sort_by { |a| a.rand_id }.paginate(:page => params[:page], :per_page => 16) 

जो अभी भी विभिन्न पृष्ठों में दोहराने वाली फिल्मों का उत्पादन करता है।इस बिंदु पर मुझे एहसास होगा कि पेजिनेट से पहले आपने जो कुछ हल किया है, वह करेगा। तो मैंने यह कोशिश की:

@movies = rand_movs.paginate(:order => 'rand_id', :page => params[:page], :per_page => 16) 

जो अभी भी रिकॉर्ड दोहराता है। : ऑर्डर -> 'rand_id' को अनदेखा किया गया है क्योंकि : ऑर्डर केवल तब मायने रखता है जब आप ActiveRecord ऑब्जेक्ट्स से निपट रहे हैं, सरणी नहीं।

तो सेटसीड (एन) will_paginate का उपयोग करके यादृच्छिक गैर-दोहराव वाले रिकॉर्ड प्राप्त करने के लिए मेरी एकमात्र आशा प्रतीत होता है। कोई विचार?

धन्यवाद!

+0

का उपयोग कर सकते हैं बीज का चयन कॉलम निर्दिष्ट करता है क्वेरी में, और आपने कोई भी नहीं, केवल बीज निर्दिष्ट किया। सुनिश्चित नहीं है कि यह काम करेगा, लेकिन इसे आजमाएं: '। चयन करें ('*, सेटसीड (1)')' – Matzi

उत्तर

18

नहीं postgres व्यक्ति लेकिन ... मैं

Movie.connection.execute "select setseed(0.5)" 
Movie.where(...).order('random()').page(params[:page]).per_page(15) 
साथ Array#shuffle के संबंध एक बीज नहीं ले रही

कोशिश करना चाहते हैं, इसे इस्तेमाल करता है Kernel.rand ताकि आप इसे Kernel.srand

+0

धन्यवाद, फ्रेडरिक। यह चाल है। इसके अलावा, सिर के लिए धन्यवाद : कर्नेल के साथ Array # shuffle बीजिंग। – jkym

+0

मैं इसे प्राप्त करने की कोशिश कर रहा हूं। यह मुझे प्रत्येक रीलोड पर एक ही यादृच्छिक क्रम देता है, लेकिन साइट पर आने वाले प्रत्येक उपयोगकर्ता के लिए मुझे एक नया यादृच्छिक क्रम कैसे मिलता है? – funkylaundry

+2

आप चाहें प्रत्येक उपयोगकर्ता के लिए एक अलग बीज पास करें –

1

select के क्षेत्रों की एक सरणी गुजर कोशिश:

@movies = movies.select(['setseed(.5)', 'some_movie_attribute']).order('random()').page(params[:page]).per_page(16) 

कुछ परिणाम some_movie_attribute, है जो आपकी क्वेरी द्वारा चयनित नहीं किया जा रहा उपयोग कर रहा है, और इसलिए उपलब्ध नहीं है। इसे चुनिंदा क्षेत्रों में से एक के रूप में जोड़ना इसे हल करना चाहिए।

+0

बहुत धन्यवाद। मैंने 'movies.select (['setseed (.5)', '*']) ऑर्डर ('यादृच्छिक()') पृष्ठ (पैराम्स [: पेज])। Per_page (16) 'जैसे सरणी को पास करना आपने सुझाव दिया है, लेकिन सभी मूवी फ़ील्ड को कॉल करने के लिए '*' के साथ (मेरा टेम्पलेट विशेषता का एक गुच्छा कॉल करता है), टेम्पलेट प्रस्तुत करता है (हुरे!)। लेकिन अब बीज सेट के साथ, रिकॉर्ड यादृच्छिक रूप से आदेश नहीं देते हैं - उन्हें आईडी द्वारा आदेश दिया जाता है इससे कोई फर्क नहीं पड़ता कि बीज क्या गुजरता है। :-( – jkym

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