I want most recent message sent by each users. Here is sample data
Table : conversations
sender receiver message date
============================================================
1 2 "hi" "2013-03-04 09:55:01.122074"
2 1 "hello" "2013-03-04 09:55:32.903975"
1 2 "have you done with the taks?" "2013-03-04 09:57:46.383007"
2 1 "almost..." "2013-03-04 09:58:55.783219"
2 1 "should be able to finish 2day" "2013-03-04 09:59:28.950705"
2 3 "shall we start?" "2013-03-04 10:01:16.842725"
3 2 "give me a minute" "2013-03-04 10:01:41.994589"
3 2 "let us start" "2013-03-04 10:02:14.04551"
Where for user with id 2, I should be able to get following two record
1 2 "have you done with the taks?" "2013-03-04 09:57:46.383007"
3 2 "let us start" "2013-03-04 10:02:14.04551"
Here is my solution
Model : User
class User < ActiveRecord::Base
has_many :chats_received, class_name: 'Conversation', foreign_key: 'receiver_id',order: "created_at DESC"
end
Model : Conversation
class Conversation < ActiveRecord::Base
attr_accessible :message, :read
belongs_to :sender, class_name: 'User'
belongs_to :receiver, class_name: 'User'
def most_recent_chat_received_from_connected_users
connected_users_chats = . . . # Get all conversations which are sent to current user. e.g., user with id 2
chats_grouped_by_senders = connected_users_chats.group_by { |conversation| conversation.sender_id }
chats_grouped_by_senders.inject([]){|memo , (sender_id, conversations)| memo << conversations.first; memo}
end
end
Get most recent message from connected users:
user = User.find 2
user.most_recent_chat_received_from_connected_users
Though this solution works, it select and create models for each conversion between two user. Also I feel it is not rails way of getting required rows.
I have been using postgresql. I have been getting following error when I try to use group method on the mode.
ActiveRecord::StatementInvalid: PG::Error: ERROR: column "conversations.id" must appear in the GROUP BY clause or be used in an aggregate function
Is there any better way to get the same results?
I'm not sure how you can call most_recent_chat_received_from_connected_users
, which is an instance method of your Conversation
class, on an instance of User
without getting an error, but i would add a custom finder to the Conversation model:
class Conversation < ActiveRecord::Base
# ...
def self.most_recent_for(user_id)
select('DISTINCT ON (sender_id) *').where(reciever_id: user_id).order("sender_id, created_at DESC")
end
# For MySQL you could have used:
#
# def self.most_recent_for(user_id)
# where(reciever_id: user_id).group("sender_id").order("created_at DESC")
# end
# ...
end
Now you can get the desired conversations in your controller with:
@conversations = Conversation.most_recent_for(current_user.id)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With