Ruby rand()不能接受变量?

时间:2010-12-02 04:37:23

标签: ruby-on-rails ruby

我对此感到有些困惑。

我在RoR项目中的最终目标是从我的数据库中获取一个随机配置文件。

我在想它会是这样的:

@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()不能接受静态整数以外的输入。

我是对的吗?怎么回事?

4 个答案:

答案 0 :(得分:9)

尝试:

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

随着数据库老化,尤其是具有用户记录的数据库,您的ID字段序列中将存在间隙。尝试随机获取ID可能会失败,因为您可能会尝试随机抓取已删除的ID。

相反,如果你计算记录的数量,那么随机转到表中的某个偏移量,你将回避丢失ID的可能性,并且只能登陆现有记录。

OPs问题中的以下示例可能遇到一些问题,除非仔细观察数据库的完整性:

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

问题是,User表可能与Profile表不同步,允许它们具有不同数量的记录。例如,如果User.count为3且Profile中有两条记录,则查找失败可能导致异常。

答案 1 :(得分:4)

我不确定为什么rand(i)没有像你期望的那样工作(它对我来说很好),但这不是一个找到随机配置文件的好方法;如果一个配置文件被删除,或者有任何用户没有配置文件,那么这将失败。

我认为在使用ActiveRecord的Rails中有一种有效的方法。对于少数用户,你可以只使用Profile.find_all()并从该数组中选择一个随机配置文件,但你可能最好做一些像

这样的事情。
@profile = Profile.find_by_sql("SELECT * FROM profiles ORDER BY RAND() LIMIT 1").first

StackOverflow还有很多关于如何在SQL中选择随机记录的问题;我认为这是最简单的,但是如果你关注效率,那么看看周围是否有更好的其他实现。

编辑:find_by_sql返回一个数组,因此您需要执行.first以获取单个配置文件。

答案 2 :(得分:1)

当我想在Rails中获取随机记录时,我会这样:

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

这通常有效,但从我之前读过的内容来看,RAND()命令是特定于MySQL的,或者至少不是数据库独立的。其他人可能会使用RANDOM()。

答案 3 :(得分:-3)

按ID IN Rails查找是多余的

@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的错误消息可能是由于RAILS Conventions Over Configuration合理的默认值,这只是人们同意的规则。

当使用rails时,没有理由让用户为0,它始终从1开始,我将其归因于DHH试图更具可读性。