Rails where на необычном подзапросе - PullRequest
2 голосов
/ 27 мая 2020

Я уже знаю, как использовать Rails для создания подзапросов в условиях where, например:

Order.where(item_id: Item.select(:id).where(user_id: 10))

Однако, как вы увидите, мой случай немного сложнее. Я пытаюсь преобразовать этот запрос:

Post.find_by_sql(
  <<-SQL
    SELECT posts.*
    FROM posts
    WHERE (
      SELECT name
      FROM moderation_events
      WHERE moderable_id = posts.id
        AND moderable_type = 'Post'
      ORDER BY created_at DESC
      LIMIT 1
    ) = 'reported'
  SQL
)

в вызов типа ActiveRecord / Arel (i sh), но пока не смог найти способ, поэтому необработанный код SQL и использование find_by_sql.

Мне интересно, сталкивался ли кто-нибудь уже с такой же проблемой и есть ли лучший способ написать этот запрос?

EDIT

Необработанный запрос выше работает и возвращает именно тот результат, который мне нужен. Я использую PostgreSQL.

Post model

class Post < ApplicationRecord
  has_many :moderation_events, as: :moderable, dependent: :destroy, inverse_of: :moderable
end

ModerationEvent model

class ModerationEvent < ApplicationRecord
  belongs_to :moderable, polymorphic: true
  belongs_to :post, foreign_key: :moderable_id, inverse_of: :moderation_events
end

EDIT 2

Я пробовал использовать ассоциации Rails для запроса, используя includes, joins и т.п. Однако приведенный выше запрос очень конкретный c и хорошо работает с этой формой. Изменение его с помощью запроса JOIN не возвращает ожидаемых результатов.

Операторы ORDER и LIMIT очень важны здесь и не могут быть перемещены за его пределы.

A post может иметь несколько moderation_events. Событие модерации может иметь несколько name (он же тип): reported, validated, moved и deleted.

Вот что делает запрос:

Получение всех сообщений с последним событием модерации как «сообщенное» событие

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

...