Rails 5: includes for polymorphic with where conditions

Viewed 708

I need to query my models and produce a record similar to this:

[{
  "subscriber": {
    "email": "user@example.com",
    "subscriptions": [{
      "confirmed": true,
      "subscriptionable": {
        "name": "Place XYZ",
        "comments": [{
          "author": "John",
          "body": "Hello."
        }]
      }
    }]
  }
}]

My models look like this:

class Subscriber < ApplicationRecord
  has_many :subscriptions
end

class Subscription < ApplicationRecord
  belongs_to :subscriptionable, polymorphic: true
  belongs_to :subscriber
end

class Place < ApplicationRecord
  has_many :subscriptions, as: :subscriptionable
  has_many :comments, as: :commentable
end

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end

So far I'm able to produce the record I want by running this query:

Subscriber.includes(subscriptions: [subscriptionable: [:comments]])

The problem is I that, with the query above, I can't specify any where conditions. For example, this will fail:

Subscriber.includes(subscriptions: [subscriptionable: [:comments]])
    .where(subscriptions: { confirmed: true })

> ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :subscriptionable

And the other issue is that I can't just get certain attributes, for example:

Subscriber.includes(subscriptions: [subscriptionable: [:comments]])
    .pluck("subscribers.email")

> ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :subscriptionable

Edit

Maybe this will help clarify: what I would like to achieve is something in the lines of this SQL query:

SELECT subscriptions.name as sub_name, subscriptions.email as sub_email, 
       places.name as place_name, comments.author as com_author, comments.body as com_body, subscribers.token
FROM subscriptions 
JOIN subscribers
ON subscriptions.subscriber_id = subscribers.id
JOIN places 
ON subscriptionable_id = places.id 
JOIN comments 
ON places.id = commentable_id 
WHERE subscriptions.confirmed 
AND subscriptionable_type = 'Place' 
AND commentable_type = 'Place' 
AND comments.status = 1 
AND comments.updated_at >= '#{1.week.ago}'
0 Answers
Related