2010-12-02 25 views
5

Bu konuda biraz şaşkınım.Ruby rand() değişkenleri kabul edemiyor?

RoR projesindeki son hedefim veritabanımdan tek bir rasgele profil almak.

bir şey gibi olurdu düşünüyordum: Bu 0 yok user_id çünkü bir hata atma tuttu

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

, bu yüzden dışarı bölümlerini sadece neler olduğunu kontrol etmek çekti:

@r = rand(User.count) 

<%= @r %> 

Bu, her seferinde 0 değerini döndürür. Yani, ne oluyor? Bunu test etmek için 5 sahte kullanıcı ve 5 ilgili profil kaydettim.

Ben Profile.find_by_user_id(rand(User.count)) alıp gayet güzel çalışıyor

Profile.find_by_user_id(3) 

olarak yeniden edin.

User.count da çalışıyor. Bu yüzden rand()'un statik bir tamsayıdan başka bir giriş yapamayacağını düşünüyorum.

Doğru muyum? Neler oluyor?

+1

rand (User.count) benim için çalışıyor. – drewrobb

+0

Gerçekten mi? Tamam hmm. Neler olduğunu görmek zorundayım. Belki kritik bir şeyi özlüyorum. – Elxx

+0

Düzenleme Andrew için teşekkürler. Kendi sorumu tekrar okuduktan sonra da bazen kafamı karıştırdım = D – Elxx

cevap

9

Dene: Bir veritabanı eskidikçe

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

, kullanıcı kayıtları ile özellikle bir, senin kimliği alanı dizide boşluklar olacaktır. Rastgele bir kimliği yakalamaya çalışmak, başarısız olma olasılığına sahip olacaktır, çünkü silinmiş olanı rastgele bir şekilde yakalamaya çalışabilirsiniz. Bunun yerine, kayıt sayısını sayarsanız, rasgele bir şekilde tabloya bir miktar sapma yaparak, kimlikleri eksik olma olasılığını ortadan kaldıracak ve yalnızca mevcut kayıtlara iniş yapabileceksiniz.

veritabanının bütünlüğünü çok dikkatli izledim sürece soru bazı sorunlarla çalıştırabilir OP'lerine aşağıdaki örnek:

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

, Kullanıcı tablo senkronizasyon dışı olmak için bir olasılık var Profil tablosuyla, farklı kayıt sayısına sahip olmalarını sağlar. Örneğin, User.count 3 ise ve Profilde iki kayıt varsa, bir istisna ile sonuçlanan başarısız bir arama için potansiyel vardır.

+0

Mükemmel. Çok iyi çalışıyor. Ben bunu en iyi cevap olarak seçtim çünkü RAND/RANDOM =) – Elxx

+1

Saygısı gibi belirli işlevlere sahip özel veritabanı. Evet, DB özelliklerini taşınabilir olarak saklamaktan kasten kaçındım. Tamamen DBM'de çalışacak şekilde yazılabilir, ancak bu sorguyu belirli bir veritabanına bağlar. Olduğu gibi, veritabanına iki çağrı yapmak zorundadır, ancak çok hızlıdır ve bir aramayı içermemelidir. –

+0

Her zaman hızlı olmak zorunda değil. Örneğin, Postgres yavaş COUNT (*) sorguları için kötü şöhretlidir. –

-3

Bulma By Kimlik İÇİNDE Raylar muhtemelen RAYLI sadece insanlar üzerinde mutabık kuralları vardır Conventions Over Configuration mantıklı varsayılan taşımaktadır

@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 dayalı hata mesajı Gereksiz olduğunu.

Ve rayları kullanırken, bir kullanıcının 0 olması için bir neden yoktur, her zaman, DHH'ye daha okunaklı olmaya çalışıyorum diye attığım 1'den başlar.

+0

Bu, onun anlattığı kadarıyla onun sorusu ile ilgisi yok. Profile.find (rand_int) 'in Profile.find_by_user_id (rand_it)' den daha mantıklı olduğunu kabul ediyorum, ancak find_by_user_id herhangi bir gerçek anlamda "gereksiz" değildir. Ayrıca yazının geri kalanının ne hakkında konuştuğunu bilmiyorum. – bnaul

+0

Üzgünüz, yazıyı daha mantıklı hale getirmeye çalışacağım. Profil.find_by_user_id adını verdiğim için 2 sütun, id ve user_id var. User_id sütununa göre satır seçmek istiyorum. Yani, çok gerekli. – Elxx

4

Neden rand (i) beklediğiniz gibi çalışmadığından emin değilim (benim için iyi çalışıyor), ancak bu rastgele bir profili bulmak için iyi bir yol değil; Bir profil silinmişse veya profilsiz herhangi bir kullanıcı varsa, bu başarısız olur.

ActiveRecord'u kullanarak Rails'de bunu yapmanın etkili bir yolu olduğunu sanmıyorum. küçük bir kullanıcı numarası için, sadece Profile.find_all (do) ve bu diziden rasgele profil seçin, ancak muhtemelen StackOverflow'daki diğer birçok soru vardır

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

böyle bir şey yaptığını daha iyi olurdu olabilirdi SQL'de rastgele bir kayıt seçmek için; Bunun en kolay olduğunu söyleyebilirim, ancak verimlilik konusunda endişeleriniz varsa, etrafınıza bir göz atın ve daha iyi sevdiğiniz başka bir uygulama olup olmadığını görün.

DÜZENLEME: find_by_sql bir dizi döndürür, böylece tek bir Profil almak için .first yapmanız gerekir. Genelde böyle

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

ama ne okudum önceki, RAND() komutu MySQL özgüdür: Rails rastgele bir rekor almak istediğinizde

+0

Bunu deneyeceğim. İnsanların profillerini silmesinin bir şeyleri berbat edeceğine hiç benzemedim .... ha test vakası yazmaya başlamalıyım. – Elxx

+0

Bunu yapmanın yolu en iyisidir (Ruby'de rasgele sayıyı oluşturmak ve daha sonra 'id' sütununda aramak) - istediği satırı bulmak için sürekli zaman alır. Yolunuzu yapmak, rastgele sayılar atamak için tam bir tablo taraması ve ihtiyaç duyduğu bir satırı döndürmeden önce bir O (n log n) sıralama gerektirir. –

+2

@Ken Bloom bu doğrudur. Aradaki fark aslında benim çalışmamdır =), oysa OP'nin bahsettiğim eksiklikler var. DanneManne'in benzer ve daha fazla Rubyish vardır, ancak rastgele bir kimlik ile bulmak tehlikeli. Bir süre döngüsüne sarılabilir ve bir veri bulunana kadar arama yapmaya devam edebilirsiniz; bu, tüm veri kümeleri için daha hızlı olur, ancak birçok eksik satır içerenler için daha yavaştır (ve potansiyel olarak sadece bir tanesinin yerine çok sayıda veritabanı isteği üretebilir). – bnaul

1

, böyle bir şey gitmek ya da en azından veritabanı bağımsız değil. Diğerleri RANDOM() kullanabilir.

İlgili konular