In my recent project, I faced a challenge with broadcasting comments in a Ruby on Rails application using Hotwire. The goal was to ensure that unpublished comments would only be visible to the user who created them, while published comments would be visible to everyone. Here’s how I tackled this issue.

This post details the changes I made to the comment model and the view to achieve the desired functionality, ensuring a smooth user experience while maintaining the integrity of the comment approval process.


The Problem

Initially, the broadcasting logic for comments was straightforward but lacked the necessary checks for unpublished comments. The existing code was broadcasting all comments to everyone, which was not ideal for comments pending approval. Additionally, the Ruby on Rails models were also lacking any information about the user session, further complicating the management of comment visibility and user interactions.


The Solution

I refactored the broadcasting logic in the Comment model to separate the concerns of creating, updating and destroying comments. Here’s a breakdown of the changes I made:

Updated Comment Model

class Comment < ApplicationRecord
  belongs_to :user
  validates_presence_of :content

  after_create_commit :broadcast_create
  after_update_commit :broadcast_update
  after_destroy_commit :broadcast_destroy

  private

  def broadcast_create
    if published
      broadcast_append_to "comments", target: "comments"
    else
      broadcast_append_to "comments_#{user.id}", target: "comments"
    end
  end

  def broadcast_update
    if published
      # now visible for everyone
      broadcast_append_to "comments", target: "comments"
      broadcast_append_to "comments_#{user.id}", target: "comments"
    else
      # no longer public → remove from everyone, but keep for author
      broadcast_remove_to "comments"
      broadcast_append_to "comments_#{user.id}", target: "comments"
    end
  end

  def broadcast_destroy
    broadcast_remove_to "comments"
    broadcast_remove_to "comments_#{user.id}"
  end
end

Updated View Logic

In the view, I modified the Turbo stream subscription to ensure that the current user only receives broadcasts for their unpublished comments. Here’s the updated code:

<% if current_user %>
  <%= turbo_stream_from "comments_#{current_user.id}" %>
<% else %>
  <%= turbo_stream_from "comments" %>
<% end %>

Conclusion

These changes not only improved the user experience by ensuring that users could see their unpublished comments but also maintained the overall integrity of the comment system. By implementing this logic, I was able to create a more robust and user-friendly application.

If you’re working with Ruby on Rails and Hotwire, I hope this solution helps you manage comment broadcasts more effectively!