Adding a chat feature to a marketplace or platform can significantly improve user engagement. Recently, I built a chat system that allows B2C users to communicate with B2B merchants through a Ruby on Rails API, with real-time notifications powered by Pusher. Here’s how I did it.
Data Model
The core of the chat feature consists of two main models:
- ChatRoom: Represents a unique conversation between a user and a listing.
- ChatMessage: Represents individual messages within a chat room.
Since messages can be sent by either users or merchants, the ChatMessage model uses a polymorphic association for the sender and receiver.
ChatRoom Model
class ChatRoom < ApplicationRecord belongs_to :user belongs_to :listing has_many :chat_messages, dependent: :destroy end
Each chat room is unique to a user and a listing, ensuring that a user doesn’t have multiple chat threads for the same listing.
ChatMessage Model
class ChatMessage < ApplicationRecord belongs_to :chat_room belongs_to :sender, polymorphic: true belongs_to :receiver, polymorphic: true after_create_commit :send_realtime_notification end
This setup allows for flexibility in sending messages from both sides—whether from a user to a merchant or vice versa.
Real-Time Notifications with Pusher
To ensure instant message updates, I integrated Pusher. When a new message is created, it triggers a real-time event.
Broadcasting Messages
In the ChatMessage model:
In the ChatMessage model:
def send_realtime_notification Pusher.trigger("chat_#{chat_room.id}", "new_message", { message: self.content, sender_id: self.sender_id, receiver_id: self.receiver_id }) end
Each chat room has its own Pusher channel, ensuring that only relevant participants receive notifications.
API Endpoints
Here’s a basic controller to handle chat messages:
class ChatMessagesController < ApplicationController before_action :set_chat_room def create message = @chat_room.chat_messages.create!(message_params) render json: message end private def set_chat_room @chat_room = ChatRoom.find(params[:chat_room_id]) end def message_params params.require(:chat_message).permit(:content, :sender_id, :sender_type, :receiver_id, :receiver_type) end end
This allows clients (mobile apps) to send messages by making a POST request to the API.
Conclusion
By structuring the data model with ChatRoom and ChatMessage, using polymorphic associations, and integrating Pusher for real-time notifications, I was able to build a flexible chat system that works seamlessly for both B2C users and B2B merchants.