From dc80459a9e9a6088668f93c9f44be4c170193fb7 Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Tue, 22 Jan 2019 14:05:32 -0500 Subject: Move `channel_name` to Channel.broadcasting_for That would allow us to test broadcasting made with channel, e.g.: ```ruby class ChatRelayJob < ApplicationJob def perform_later(room, msg) ChatChannel.broadcast_to room, message: msg end end ``` To test this functionality we need to know the underlying stream name (to use `assert_broadcasts`), which relies on `channel_name`. We had to use the following code: ```ruby assert_broadcasts(ChatChannel.broadcasting_for([ChatChannel.channel_name, room]), 1) do ChatRelayJob.perform_now end ``` The problem with this approach is that we use _internal_ API (we shouldn't care about `channel_name` prefix in our code). With this commit we could re-write the test as following: ```ruby assert_broadcasts(ChatChannel.broadcasting_for(room), 1) do ChatRelayJob.perform_now end ``` --- actioncable/lib/action_cable/channel/broadcasting.rb | 19 ++++++++++++------- actioncable/lib/action_cable/channel/streams.rb | 2 +- actioncable/lib/action_cable/channel/test_case.rb | 4 +--- actioncable/test/channel/broadcasting_test.rb | 15 ++++++++++++--- 4 files changed, 26 insertions(+), 14 deletions(-) (limited to 'actioncable') diff --git a/actioncable/lib/action_cable/channel/broadcasting.rb b/actioncable/lib/action_cable/channel/broadcasting.rb index 9a96720f4a..bd900e1c65 100644 --- a/actioncable/lib/action_cable/channel/broadcasting.rb +++ b/actioncable/lib/action_cable/channel/broadcasting.rb @@ -12,17 +12,22 @@ module ActionCable module ClassMethods # Broadcast a hash to a unique broadcasting for this model in this channel. def broadcast_to(model, message) - ActionCable.server.broadcast(broadcasting_for([ channel_name, model ]), message) + ActionCable.server.broadcast(broadcasting_for(model), message) end - def broadcasting_for(model) #:nodoc: + # Returns a unique broadcasting identifier for this model in this channel. + def broadcasting_for(model) + serialize_broadcasting([ channel_name, model ]) + end + + def serialize_broadcasting(object) #:nodoc: case - when model.is_a?(Array) - model.map { |m| broadcasting_for(m) }.join(":") - when model.respond_to?(:to_gid_param) - model.to_gid_param + when object.is_a?(Array) + object.map { |m| serialize_broadcasting(m) }.join(":") + when object.respond_to?(:to_gid_param) + object.to_gid_param else - model.to_param + object.to_param end end end diff --git a/actioncable/lib/action_cable/channel/streams.rb b/actioncable/lib/action_cable/channel/streams.rb index 81c2c38064..7e1ed3c850 100644 --- a/actioncable/lib/action_cable/channel/streams.rb +++ b/actioncable/lib/action_cable/channel/streams.rb @@ -99,7 +99,7 @@ module ActionCable # Pass coder: ActiveSupport::JSON to decode messages as JSON before passing to the callback. # Defaults to coder: nil which does no decoding, passes raw messages. def stream_for(model, callback = nil, coder: nil, &block) - stream_from(broadcasting_for([ channel_name, model ]), callback || block, coder: coder) + stream_from(broadcasting_for(model), callback || block, coder: coder) end # Unsubscribes all streams associated with this channel from the pubsub queue. diff --git a/actioncable/lib/action_cable/channel/test_case.rb b/actioncable/lib/action_cable/channel/test_case.rb index c4cf0ac0e7..19d6f1cccf 100644 --- a/actioncable/lib/action_cable/channel/test_case.rb +++ b/actioncable/lib/action_cable/channel/test_case.rb @@ -300,9 +300,7 @@ module ActionCable def broadcasting_for(stream_or_object) return stream_or_object if stream_or_object.is_a?(String) - self.class.channel_class.broadcasting_for( - [self.class.channel_class.channel_name, stream_or_object] - ) + self.class.channel_class.broadcasting_for(stream_or_object) end end diff --git a/actioncable/test/channel/broadcasting_test.rb b/actioncable/test/channel/broadcasting_test.rb index 2cbfabc1d0..fb501a1bc2 100644 --- a/actioncable/test/channel/broadcasting_test.rb +++ b/actioncable/test/channel/broadcasting_test.rb @@ -26,14 +26,23 @@ class ActionCable::Channel::BroadcastingTest < ActionCable::TestCase end test "broadcasting_for with an object" do - assert_equal "Room#1-Campfire", ChatChannel.broadcasting_for(Room.new(1)) + assert_equal( + "action_cable:channel:broadcasting_test:chat:Room#1-Campfire", + ChatChannel.broadcasting_for(Room.new(1)) + ) end test "broadcasting_for with an array" do - assert_equal "Room#1-Campfire:Room#2-Campfire", ChatChannel.broadcasting_for([ Room.new(1), Room.new(2) ]) + assert_equal( + "action_cable:channel:broadcasting_test:chat:Room#1-Campfire:Room#2-Campfire", + ChatChannel.broadcasting_for([ Room.new(1), Room.new(2) ]) + ) end test "broadcasting_for with a string" do - assert_equal "hello", ChatChannel.broadcasting_for("hello") + assert_equal( + "action_cable:channel:broadcasting_test:chat:hello", + ChatChannel.broadcasting_for("hello") + ) end end -- cgit v1.2.3 From 35bef64718f85ef550916f840fd10a9288185577 Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Tue, 22 Jan 2019 14:31:51 -0500 Subject: Add Channel#broadcast_to --- actioncable/lib/action_cable/channel/broadcasting.rb | 2 +- actioncable/test/channel/test_case_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'actioncable') diff --git a/actioncable/lib/action_cable/channel/broadcasting.rb b/actioncable/lib/action_cable/channel/broadcasting.rb index bd900e1c65..6c7aec49e3 100644 --- a/actioncable/lib/action_cable/channel/broadcasting.rb +++ b/actioncable/lib/action_cable/channel/broadcasting.rb @@ -7,7 +7,7 @@ module ActionCable module Broadcasting extend ActiveSupport::Concern - delegate :broadcasting_for, to: :class + delegate :broadcasting_for, :broadcast_to, to: :class module ClassMethods # Broadcast a hash to a unique broadcasting for this model in this channel. diff --git a/actioncable/test/channel/test_case_test.rb b/actioncable/test/channel/test_case_test.rb index 9c360d5dc3..a166c41e11 100644 --- a/actioncable/test/channel/test_case_test.rb +++ b/actioncable/test/channel/test_case_test.rb @@ -180,7 +180,7 @@ class BroadcastsTestChannel < ActionCable::Channel::Base def broadcast_to_user(data) user = User.new user_id - self.class.broadcast_to user, text: data["message"] + broadcast_to user, text: data["message"] end end -- cgit v1.2.3 From 513dd2cfdb98c01bce9759b29c48aa8b691f53d4 Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Tue, 22 Jan 2019 15:06:16 -0500 Subject: Add note about broadcast_to/broadcasting_for to change log --- actioncable/CHANGELOG.md | 19 +++++++++++++++++++ actioncable/lib/action_cable/channel/broadcasting.rb | 7 ++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'actioncable') diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 4109dd6138..7f3177b64e 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,22 @@ +* Add `Channel::Base#broadcast_to`. + + You can now call `broadcast_to` within a channel action, which equals to + the `self.class.broadcast_to`. + + *Vladimir Dementyev* + +* Make `Channel::Base.broadcasting_for` a public API. + + You can use `.broadcasting_for` to generate a unique stream identifier within + a channel for the specified target (e.g. Active Record model): + + ```ruby + ChatChannel.broadcasting_for(model) # => "chat:" + ``` + + *Vladimir Dementyev* + + ## Rails 6.0.0.beta1 (January 18, 2019) ## * Merge [`action-cable-testing`](https://github.com/palkan/action-cable-testing) to Rails. diff --git a/actioncable/lib/action_cable/channel/broadcasting.rb b/actioncable/lib/action_cable/channel/broadcasting.rb index 6c7aec49e3..9f702e425e 100644 --- a/actioncable/lib/action_cable/channel/broadcasting.rb +++ b/actioncable/lib/action_cable/channel/broadcasting.rb @@ -15,7 +15,12 @@ module ActionCable ActionCable.server.broadcast(broadcasting_for(model), message) end - # Returns a unique broadcasting identifier for this model in this channel. + # Returns a unique broadcasting identifier for this model in this channel: + # + # CommentsChannel.broadcasting_for("all") # => "comments:all" + # + # You can pass any object as a target (e.g. Active Record model), and it + # would be serialized into a string under the hood. def broadcasting_for(model) serialize_broadcasting([ channel_name, model ]) end -- cgit v1.2.3 From cfe65cb478a44f19f3b4562cd1cf3c99d2cb930b Mon Sep 17 00:00:00 2001 From: Vladimir Dementyev Date: Tue, 22 Jan 2019 16:53:01 -0500 Subject: fix fixture syntax in cable docs and guides --- actioncable/lib/action_cable/channel/test_case.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'actioncable') diff --git a/actioncable/lib/action_cable/channel/test_case.rb b/actioncable/lib/action_cable/channel/test_case.rb index 19d6f1cccf..b05d51a61a 100644 --- a/actioncable/lib/action_cable/channel/test_case.rb +++ b/actioncable/lib/action_cable/channel/test_case.rb @@ -143,7 +143,7 @@ module ActionCable # You need to set up your connection manually to provide values for the identifiers. # To do this just use: # - # stub_connection(user: users[:john]) + # stub_connection(user: users(:john)) # # == Testing broadcasting # @@ -157,9 +157,9 @@ module ActionCable # end # # def test_speak - # subscribe room_id: rooms[:chat].id + # subscribe room_id: rooms(:chat).id # - # assert_broadcasts_on(rooms[:chat], text: "Hello, Rails!") do + # assert_broadcasts_on(rooms(:chat), text: "Hello, Rails!") do # perform :speak, message: "Hello, Rails!" # end # end -- cgit v1.2.3