Switch to tighter Channel scoping...

This is not a normal pattern for setting up ActionCable channels, so it might need some notes. It ensures the broadcasts from the ReportJob are unique not just to the user session but also to the specific tab in the user's browser. Otherwise if the user has two different report pages open in separate tabs with the same session, the broadcast would overwrite the #report-table element in both of them.
This commit is contained in:
Matt-Yorkley
2023-05-02 22:48:45 +01:00
committed by Maikel Linke
parent a3ef604797
commit 524d1f0264
4 changed files with 39 additions and 2 deletions

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
class ScopedChannel < ApplicationCable::Channel
class << self
def for_id(id)
"ScopedChannel:#{id}"
end
end
def subscribed
stream_from "ScopedChannel:#{params[:id]}"
end
end

View File

@@ -67,7 +67,7 @@ module Admin
@blob = ReportBlob.create_for_upload_later!(report_filename)
ReportJob.perform_later(
report_class, spree_current_user, params, format, @blob, SessionChannel.for_request(request)
report_class, spree_current_user, params, format, @blob, ScopedChannel.for_id(params[:uuid])
)
render cable_ready: cable_car.

View File

@@ -6,6 +6,8 @@
- options = @background_reports ? { data: { remote: "true" } } : {}
= form_for @report.search, { url: url_for }.merge(options) do |f|
= hidden_field_tag "uuid", request.uuid
%fieldset.no-border-bottom.print-hidden
%legend{ align: 'center'}= t(:report_filters)
= render partial: "admin/reports/filters/#{@report_type}", locals: { f: f }
@@ -27,5 +29,5 @@
= t(@error, link: link_to(t(".report_link_label"), @error_url)) if @error
#report-table
#report-table{ data: { controller: "scoped-channel", "scoped-channel-id-value": request.uuid } }
= @table

View File

@@ -0,0 +1,22 @@
import { Controller } from "stimulus";
import consumer from "../channels/consumer";
import CableReady from "cable_ready";
export default class extends Controller {
static values = { id: String };
connect() {
this.subscription = consumer.subscriptions.create(
{ channel: "ScopedChannel", id: this.idValue },
{
received(data) {
if (data.cableReady) CableReady.perform(data.operations);
},
}
);
}
disconnect() {
consumer.subscriptions.remove(this.subscription);
}
}