2015-10-08 3 views
0

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

Итак, теперь я пытаюсь получить массив сообщений с уникальными пользователями по приведенному ниже коду. Но мне кажется, что массивы все те же и не уникальны.

Вот код:

<% post.messages.uniq{|x| x.user_id}.each do |m| %> 
    ... 
<% end %> 

ответ

0

Устаревшей .uniq_by метод будет работать я полагаю. В документации предлагается использовать Array.uniq вместо этого, но это не то же самое. (Array.uniq игнорирование данного блока)

Если вы не хотите использовать .uniq_by, попробуйте это: post.messages.group(:user_id)

+1

У меня все еще недостаточно репутации для +1, но это работает так хорошо! –

+0

однако это не работает с PostgreSQL (HEROKU) –

2

Я предполагаю, что post является объектом ActiveRecord и messages является has_many отношением на этот класс.

При вызове post.messages вы не сразу получаете массив. Вместо этого Rails сначала создает объект ActiveRecord::Relation, который содержит запрос, который вы только что создали, прежде чем он будет выполнен. Это позволяет вам подключать методы поиска (например, where, select, ...) и создавать полный запрос перед его отправкой в ​​базу данных для его выполнения.

Теперь, поскольку у вас нет массива, его методы могут работать по-разному (и принимать разные аргументы), чем методы Array. Метод uniq в этом случае является псевдонимом distinct, который указывает, что запрос должен быть создан как DISTINCT. Поскольку вы еще не имеете дело с реальным массивом объектов, фильтрация с помощью блока пока не работает.

Чтобы решить эту проблему, у вас есть два варианта:

  • Вы можете заставить ActiveRecord для выполнения запроса и возвращает массив с помощью метода to_a, где вы можете использовать uniq метод массива с блоком как вы пытались выше:

    post.messages.to_a.uniq { |x| x.user_id } 
    
  • вы можете создать соответствующий запрос возвращает только данные, которые вы на самом деле нужно. Это может быть сложным в этом случае, поскольку требуемый SQL, вероятно, довольно сложный и может не поддерживаться генератором запросов ActiveRecord (и это будет создано вручную). См. this question, чтобы узнать, как создать соответствующие запросы.

+0

Я попытался использовать ваш первый метод, и uniq все еще не имеет никакого эффекта. Когда я смотрю на журнал, это то, что у нас есть в MYSQL: Загрузка сообщения (0.2мс) SELECT DISTINCT "messages". * FROM "messages" WHERE "messages". "Post_id" =? ORDER BY "messages". "Created_at" DESC [["post_id", 1]] –

+0

также кажется, что это не работает с PostgreSQL (HEROKU) –

+0

При вызове 'uniq' в' ActiveRecord :: Relation' это именно то, что должно произойти: добавление ключевого слова 'DISTINCT' в SQL-запрос, который имеет [очень специфическое значение] (http://www.tutorialspoint.com/sql/sql-distinct-keyword.htm) в SQL. К сожалению, оказывается, что '# all' изменил свой смысл с тех пор. Я обновил свой ответ соответственно. –