我对此感到有些困惑。
我在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()
不能接受静态整数以外的输入。
我是对的吗?怎么回事?
答案 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)
@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试图更具可读性。