Ruby rand () не может принимать переменные? - PullRequest
5 голосов
/ 02 декабря 2010

Я немного сбит с толку этим.

Моя конечная цель в проекте 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 ]

9 голосов
/ 02 декабря 2010

Попробуйте:

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

По мере старения базы данных, особенно с записями пользователей, в последовательности полей идентификаторов будут пробелы. Попытка произвольного получения идентификатора может привести к сбою, так как вы можете попытаться случайно получить удаленный идентификатор.

Вместо этого, если вы посчитаете количество записей, а затем случайным образом перейдете к некоторому смещению в таблице, вы обойдете возможность отсутствия пропущенных идентификаторов и окажетесь только на существующих записях.

Следующий пример из вопроса OPs может столкнуться с некоторыми проблемами, если не следить за целостностью базы данных:

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

Проблема в том, что таблица User может быть не синхронизирована с таблицей Profile, что позволяет им иметь различное количество записей. Например, если User.count было 3, а в профиле было две записи, существует вероятность неудачного поиска, что приведет к исключению.

4 голосов
/ 02 декабря 2010

Я не уверен, почему rand (i) работает не так, как вы ожидаете (у меня это работает нормально), но это не очень хороший способ найти случайный профиль независимо от того; если профиль удален или есть пользователи без профилей, это не удастся.

Я не думаю, что есть эффективный способ сделать это в Rails, используя ActiveRecord. Для небольшого числа пользователей вы можете просто выполнить Profile.find_all () и выбрать случайный профиль из этого массива, но вам, вероятно, будет лучше сделать что-то вроде

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

В StackOverflow есть много других вопросов о том, как выбрать случайную запись в SQL; Я бы сказал, что это проще всего, но если вы беспокоитесь об эффективности, посмотрите вокруг и посмотрите, есть ли другая реализация, которая вам больше нравится.

РЕДАКТИРОВАТЬ: find_by_sql возвращает массив, поэтому вам нужно сделать .first, чтобы получить один профиль.

1 голос
/ 02 декабря 2010

Когда я хочу получить случайную запись в Rails, я делаю что-то вроде этого:

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

Обычно это работает, но из того, что я прочитал ранее, команда RAND () специфична для MySQL или, по крайней мере, не зависит от базы данных. Другие могут использовать RANDOM ().

0 голосов
/ 02 декабря 2010

Поиск по идентификатору 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, которые являются просто правилами, с которыми согласны люди.

И при использовании рельсов нет причины иметь пользователя равным 0, он всегда начинается с 1, который я приписываю DHH, пытаясь быть более читабельным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...