Rails where on unusual subquery

Viewed 48

I already know how to use Rails to create subquery within a where condition, like so:

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

However, my case is a little bit more tricky as you'll see. I'm trying to convert this query:

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
)

into an ActiveRecord/Arel-like(ish) call but couldn't find a way so far, therefore the raw SQL code and the use of find_by_sql.

I'm wondering if anyone out there already faced the same issue and if there's a better way to write this query ?

EDIT

The raw query above is working and returns exactly the result I want. I'm using 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

I had tried to used Rails associations to query it, using includes, joins and the like. However, the query above is very specific and work well with that form. Altering it with a JOIN query does not return the expected results.

The ORDER and LIMIT statement are very important here and cannot be moved outside of it.

A post can have multiple moderation_events. A moderation event can have multiple name (a.k.a type): reported, validated, moved and deleted.

Here is what the query is doing:

Getting all posts having their last moderation event to be a 'reported' event

I'm not trying to alter the query above because it does works well and fast in our case. I'm just trying to convert it in a more active record fashion without changing it, if possible

0 Answers
Related