1

I have a very janky query that I'm trying to optimize. I want to return an activerecord association of user records based on some membership packet logic.

ids = User.joins(:memberships).includes(:memberships).select do |user|
  if user.memberships.count <= 1
    user.membership_packet_sent_at.blank?
  else
    user.membership_packet_sent_at.blank? && user.current_membership.created_more_than_30_days_ago?
  end
end.uniq.map(&:id)

User.where(id: ids)

The issue I am running into above is that I have to make two queries since I don't know how to use select to return an active record association instead of an array.

  1. How do I return an activerecord association from select?
  2. Is there a better way for me to organize my logic inside the select block?

Edit:

After some refactoring, I was able to move some of the select logic into methods:

```

ids = User.joins(:memberships)
          .where(membership_packet_sent_at: nil)
          .select(&:current_membership_packet_expired?)
          .uniq
          .map(&:id)

User.where(id: ids)

```

Still running into the issue of how to return an activerecord association instead

Huy
  • 10,806
  • 13
  • 55
  • 99
  • I wouldn't go so far as to say this is very janky. The main optimization error beginners usually have is N+1 (queries inside an iteration), which you've prevented via `preload`. – max pleaner Mar 26 '17 at 23:17
  • @maxple fair point. after cleaning up the method in select and reading aegis's solution, it made more sense. thanks. – Huy Mar 27 '17 at 18:31

1 Answers1

1

I don't think it is currently possible to directly return a Relation object after applying a select.

These are the main reasons that I could think about:

  • A Relation object is just a SQL builder and doesn't work with the actual data
  • The select method allows to execute custom processes that cannot be represented as a valid SQL query, so it won't be possible to chain the result of the select with another query like where

This answer also states a similar line of thought.

Community
  • 1
  • 1
Rene Hernandez
  • 1,546
  • 13
  • 20