Reputation: 1708
I have somewhat of a convoluted setup.
I am querying all users that have a thread (Conversations
) of messages.
My User model has a has_many
relation on two columns in Conversation
has_many :sender_conversations, class_name: 'Conversation', foreign_key: "sender_id", dependent: :destroy
has_many :recipient_conversations, class_name: 'Conversation', foreign_key: "recipient_id", dependent: :destroy
I needed a way to get the latest conversation since any user can have multiple threads.
To achieve this, I have the following methods on the user model:
def conversations
sender_conversations.or(recipient_conversations)
end
def latest_conversation
conversations.order(updated_at: :desc).first
end
Conversation model:
class Conversation < ApplicationRecord
...
belongs_to :sender, foreign_key: :sender_id, class_name: 'User'
belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User'
...
validates :sender_id, uniqueness: { scope: [:recipient_id, :property_id] }
scope :between, ->(sender_id, recipient_id) do
where(sender_id: sender_id, recipient_id: recipient_id).or(
where(sender_id: recipient_id, recipient_id: sender_id)
)
end
...
The controller action is querying users that have either a sender_id
or recipient_id
def users_with_existing_conversations
authorize! :users_with_existing_conversations, Conversation
@users = User.accessible_by(current_ability, :index_conversations)
@users = @users.where(id: Conversation.select(:sender_id))
.or(@users.where(id: Conversation.select(:recipient_id)))
...
end
Then finally, in the view, I'm looping through
<% @users.each do |user| %>
<tr class="table__row" onclick="window.location.href = '/conversations?user_id=<%= user.id %>'">
<td><%= user.name %>(<%= user.id %>)</td>
<td><%= user.surname %></td>
<td><%= user.email %></td>
<td><%= user.company_name.present? ? user.company_name : "N/A" %></td>
<td><%= user.role.capitalize %></td>
<td><%= user.created_at.try(:strftime, '%b %d, %Y') %></td>
<td><%= user.latest_conversation.updated_at.localtime.strftime('%b %d, %Y at %l:%M %p') %></td>
<td class="table__more">
<%= link_to "Show details", conversations_path(user_id: user.id), class: 'table__row__details button button--tertiary button--tertiary-small' %>
</td>
</tr>
<% end %>
Now what I can't figure out is how to order these rows by the latest_conversation
which is the updated_at
column.
So I have a users table I'm querying, but I want to order the query by their relation with the conversations table's updated_at
column.
Upvotes: 1
Views: 69
Reputation: 33481
You can try with a custom INNER JOIN
using the IN
clause to check both conversations
' columns:
User.joins('INNER JOIN conversations c ON users.id IN (c.sender_id, c.recipient_id)')
.order('c.created_at')
Upvotes: 1