diff --git a/app/controllers/concerns/cached_responses.rb b/app/controllers/concerns/cached_responses.rb index 05d7be1..b17e29a 100644 --- a/app/controllers/concerns/cached_responses.rb +++ b/app/controllers/concerns/cached_responses.rb @@ -10,7 +10,7 @@ module CachedResponses end def perform_caching - return false unless super && @response_cache_version.present? && !ActiveRecord::Base.connection_pool.active_connection?&.transaction_open? + return false unless super && @response_cache_version.present? && !FragmentCache.transaction_open? # Check again after authentication, before the first native fragment lookup. # Later renders retain this immutable namespace and cannot poison a new epoch. @@ -103,7 +103,7 @@ module CachedResponses !authenticated_by.bot_key? && flash.empty? && !request.headers["If-None-Match"] && !request.headers["If-Modified-Since"] && !Rails.application.config.content_security_policy_nonce_generator && - !ActiveRecord::Base.connection_pool.active_connection?&.transaction_open? + !FragmentCache.transaction_open? end def response_cache_key(encoding) diff --git a/app/models/fragment_cache.rb b/app/models/fragment_cache.rb index bb0f7e9..40147b3 100644 --- a/app/models/fragment_cache.rb +++ b/app/models/fragment_cache.rb @@ -13,4 +13,8 @@ class FragmentCache def self.store STORE end + + def self.transaction_open? + ActiveRecord::Base.connection_pool.with_connection(&:transaction_open?) + end end diff --git a/app/models/record_cache.rb b/app/models/record_cache.rb index 2446093..1db362d 100644 --- a/app/models/record_cache.rb +++ b/app/models/record_cache.rb @@ -2,7 +2,7 @@ # The observer must still see the captured epoch after lookup and admission. class RecordCache def self.fetch(key, version) - return yield unless version && ResponseCache.instance.budget.positive? && !ActiveRecord::Base.connection_pool.active_connection?&.transaction_open? + return yield unless version && ResponseCache.instance.budget.positive? && !FragmentCache.transaction_open? key = ActiveSupport::Cache.expand_cache_key([ "record-snapshot-v1", version, key ]) return yield if key.bytesize > ResponseCache::MAX_KEY_BYTES diff --git a/app/views/messages/_actions.html.erb b/app/views/messages/_actions.html.erb index 48973d6..8948783 100644 --- a/app/views/messages/_actions.html.erb +++ b/app/views/messages/_actions.html.erb @@ -12,14 +12,15 @@
<% boost_path = message_boosts_path(message) %> + <% boost_frame = dom_id(message, :boosting) %> <% EmojiHelper::REACTIONS.each do |character, title| %> - <%= form_with url: boost_path, data: { turbo_frame: dom_id(message, :boosting), action: "popup#close"} do |form| %> +
<%= hidden_field_tag "boost[content]", character %> - <%= form.button type: "submit", title: title, class: "btn message__action-btn", data: { emoji: character } do %> + +
<% end %> <%= link_to new_message_boost_path(message), @@ -31,7 +32,7 @@
- <% if message.content_type.attachment? %> + <% if message.attachment? %> <%= link_to rails_blob_path(message.attachment, disposition: "attachment", only_path: true), class: "btn message__action-btn center full-width hide-in-ios-pwa", title: "Download", aria: { label: "Download" } do %> <%= image_tag "download.svg", class: "colorize--black", size: 20, aria: { hidden: "true" } %> <% end %> diff --git a/test/controllers/messages/boosts_controller_test.rb b/test/controllers/messages/boosts_controller_test.rb index 733741e..8599892 100644 --- a/test/controllers/messages/boosts_controller_test.rb +++ b/test/controllers/messages/boosts_controller_test.rb @@ -31,6 +31,32 @@ class Messages::BoostsControllerTest < ActionDispatch::IntegrationTest end end + test "quick boost controls submit their displayed reaction to the message" do + get room_url(@message.room) + forms = css_select("##{dom_id(@message)} .quick-boosts form") + assert_equal EmojiHelper::REACTIONS.size, forms.size + forms.each do |form| + assert_equal "post", form["method"] + assert_equal message_boosts_path(@message), form["action"] + assert_equal dom_id(@message, :boosting), form["data-turbo-frame"] + assert_equal "popup#close", form["data-action"] + input = form.at_css('input[name="boost[content]"]') + button = form.at_css('button[type="submit"]') + assert_equal input["value"], button["data-emoji"] + assert_equal EmojiHelper::REACTIONS.fetch(input["value"]), button["title"] + assert_nil form.at_css('input[name="authenticity_token"]') + end + + form = forms.first + reaction = form.at_css('input[name="boost[content]"]')["value"] + assert_difference -> { @message.boosts.count }, 1 do + post form["action"], params: { boost: { content: reaction } }, headers: { + "Sec-Fetch-Site" => "same-origin", "Origin" => "http://www.example.com" } + assert_redirected_to message_boosts_url(@message) + end + assert_equal reaction, @message.boosts.order(:id).last.content + end + test "destroy" do assert_turbo_stream_broadcasts [ @message.room, :messages ], count: 1 do assert_difference -> { @message.boosts.count }, -1 do