开发者

Ruby rand() cannot accept variables?

I'm a little baffled by this.

My end goal in a RoR project is to grab a single random profile from my database.

I was thinking it would be something like:

@profile = Profile.find_by_use开发者_如何学Cr_id(rand(User.count))

It kept throwing an error because user_id 0 doesn't exist, so I pulled parts of it out just to check out what's going on:

@r = rand(User.count)

<%= @r %>

This returns 0 every time. So what's going on? I registered 5 fake users and 5 related profiles to test this.

If I take Profile.find_by_user_id(rand(User.count)) and rewrite it as

Profile.find_by_user_id(3)

it works just fine.

User.count is working too. So I think that rand() can't take an input other than a static integer.

Am I right? Whats going on?


Try:

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

As a database ages, especially one with user records, there will be gaps in your ID field sequence. Trying to grab an ID at random will have a potential to fail because you might try to randomly grab one that was deleted.

Instead, if you count the number of records, then randomly go to some offset into the table you will sidestep the possibility of having missing IDs, and only be landing on existing records.

The following example from the OPs question could run into some problems unless the integrity of the database is watched very carefully:

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

The problem is, there's a possibility for the User table to be out of sync with the Profile table, allowing them to have different numbers of records. For instance, if User.count was 3 and there were two records in Profile there's potential for a failed lookup resulting in an exception.


I'm not sure why rand(i) isn't working as you expect (it works fine for me), but this isn't a good way to find a random profile regardless; if a profile is ever deleted, or there are any users without profiles, then this will fail.

I don't think there's an efficient way to do this in Rails using ActiveRecord. For a small number of users, you could just do Profile.find_all() and select a random profile from that array, but you'd probably be better off doing something like

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

There are many other questions on StackOverflow about how to select a random record in SQL; I'd say this is the easiest, but if you're concerned about efficiency then have a look around and see if there's another implementation you like better.

EDIT: find_by_sql returns an array, so you need to do .first to get a single Profile.


When I want to get a random record in Rails, I go something like this:

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

This usually works, but from what I've read earlier, the RAND() command is specific to MySQL or at least not database independent. Others might use RANDOM().


Finding By ID IN Rails is Redundant

@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

The error message based on 0 is probably because of RAILS Conventions Over Configuration sensible defaults which are just rules people agree upon.

And when using rails there is no reason to have a user as 0, it always starts at 1 which I attribute to DHH trying to be more readable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜