Reputation: 1237
In Rails 4, I have a model Thread
which has_many
Emails
. Each Email
has a field named internal_date
. I want to return a collection of threads, ordered in a way where the thread with the latest email.internal_date
comes first (very similar to how Gmail would sort its inbox).
This is the current line in my controller (not ordering them so far):
@threads = selected_threads.joins(:tags).filter(params_filters).includes(:emails, [some other stuff]).distinct.all.paginate(page: params[:page], :per_page => 10)
I'm doing the joins
because of the filtering; and using includes
to speed things up.
Ideally I would add a scope order_by_latest_email
to my Thread
model, without killing the loading time with too many DB queries. Any tips?
Thanks!
Upvotes: 1
Views: 382
Reputation: 3053
I think this is only possible with a really ugly query like so:
Thread.joins(:emails)
.select('threads.*, emails.internal_date')
.joins('LEFT OUTER JOIN emails em ON (emails.internal_date < em.internal_date and emails.thread_id = em.thread_id)')
.where('em.id IS NULL').order('emails.internal_date DESC')
# additional filters here
You can see details in a blog post here, but this is a semi common sql problem known as the greatest n per group.
You need to find the latest email internal date in the group of emails connected to a thread. So what you do is:
em
represents that other email) has a later internal_date
(that's what the em.id IS NULL
is doing)internal_date
.Upvotes: 2