diff --git a/engine/app/views/coplan/comments/_comment.html.erb b/engine/app/views/coplan/comments/_comment.html.erb
index e5a27b8..774aa64 100644
--- a/engine/app/views/coplan/comments/_comment.html.erb
+++ b/engine/app/views/coplan/comments/_comment.html.erb
@@ -1,5 +1,5 @@
<%# Per-viewer affordances (Delete) are hidden client-side by the
- comment_actions Stimulus controller — broadcasts render once with no
+ comment_actions Stimulus controller — one broadcast is shared with every
`current_user`, so we ship the button on every human comment and let
the browser remove it for non-authors. Server still enforces auth. %>
- <%= cache(comment) do %>
+ <%# The record version invalidates edits; bump this namespace when Markdown rendering changes. %>
+ <%= cache(["comment-body-v1", comment], skip_digest: true) do %>
<%= render_markdown(comment.body_markdown) %>
<% end %>
diff --git a/spec/requests/comments_spec.rb b/spec/requests/comments_spec.rb
index 13cf315..c6fa5cc 100644
--- a/spec/requests/comments_spec.rb
+++ b/spec/requests/comments_spec.rb
@@ -19,6 +19,22 @@
expect(comment.author_id).to eq(alice.id)
end
+ it "does not calculate a template digest while broadcasting a reply" do
+ original_perform_caching = ActionController::Base.perform_caching
+ ActionController::Base.perform_caching = true
+ allow(ActionView::Digestor).to receive(:digest).and_call_original
+ allow(Rails.cache).to receive(:read).and_call_original
+
+ post plan_comment_thread_comments_path(plan, thread_record), params: {
+ comment: { body_markdown: "This should return without digesting the partial." }
+ }
+
+ expect(Rails.cache).to have_received(:read)
+ expect(ActionView::Digestor).not_to have_received(:digest)
+ ensure
+ ActionController::Base.perform_caching = original_perform_caching
+ end
+
describe "DELETE destroy" do
let!(:comment) do
create(:comment, comment_thread: thread_record, author_type: "human", author_id: alice.id, body_markdown: "to be deleted")