#ruby-on-rails #ruby #arel
Вопрос:
У меня есть модель под названием Post (таблица posts
), которая связана с моделью под названием User (таблица users
), на которую в модели Post ссылаются как на «загрузчика» (в таблице posts есть столбец uploader_id
, который называется id
«пользователи таблицы»). У пользователя может быть много записей, некоторые из которых могут быть удалены (помечены в is_deleted
логическом столбце posts
).
Как мне получить список пользователей с указанием общего количества и удаленных сообщений?
::Post
.select(
Arel.star.count.as("total"),
Arel::Nodes::Case.new.when(Post.arel_table[:is_deleted]).then(1).sum.as("deleted_count"),
:uploader
)
.joins(:uploader)
.group(:uploader)
.order(:total, :deleted_count)
.limit(20)
Это не работает. Мне нужно, чтобы пользователь был возвращен в качестве модели, идентификатора uploader_id недостаточно.
Я пробовал много попыток сделать это, но что бы я ни делал, я не могу этого понять. Либо он пытается вставить «#
Что меня крайне расстраивает, так это то, что вместо этого это работает, если мне нужно только общее количество сообщений и пользователь:
::Post
.joins(:uploader)
.group(:uploader)
.order(Arel.sql("count(*) desc"))
.limit(20)
.count
Я просто не могу понять, как добавить сумму условного случая, я новичок в rails, и документация не помогает.
Ответ №1:
«Как мне получить список пользователей с количеством общих и удаленных сообщений?», похоже, вы идете в неверном направлении. Лучше начать User
с того, что вы хотите User
, чтобы объекты возвращались.
Также Post.arel_table[:is_deleted]
не является условием, которым это должно быть Post.arel_table[:is_deleted].eq(1)
, или что-то «истинное» в вашей базе данных.
Вместо этого попробуйте выполнить следующее:
User.left_joins(:posts)
.select(
User.arel_table[Arel.star],
Post.arel_table[Arel.star].count.as('total_posts'),
Arel::Nodes::Case.new
.when(Post.arel_table[:is_deleted].eq(1)).then(1)
.else(0).sum.as('deleted_count'))
.group(:id)
.order(
Post.arel_table[Arel.star].count,
Arel::Nodes::Case.new
.when(Post.arel_table[:is_deleted].eq(1)).then(1)
.else(0).sum)
.limit(20)
Комментарии:
1. Хороший ответ. Если вы используете Postgres, вы можете использовать
count(posts.*) filter where is_deleted
вместо заявления о случае.2. @макс очень милый. К сожалению, одно из мест
Arel
не подходит. В то время как я не удосужился попробовать в данный момент (хотя в какой-то момент, вероятно, я это сделаю) Я не могу себе представить, насколько запутанным будет выглядеть это выражение, написанное с помощьюArel
объектов.