actioncable 7.2.3 → 8.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88ac9e42c67cca041d0460a69d0c15d4ae29a219701f121f04204a70b750c038
4
- data.tar.gz: 2a6d999d4e3249b3b0bc8ea7434df42de661b18b34242ab2b35c4971d0701baa
3
+ metadata.gz: e46234a70b3fa658b532b76c3f49bc9edf8daba673caad218ea165bef8c898ea
4
+ data.tar.gz: 598d01f562938624e0471e330d433a679764d4d4f88fdbdacdbe834eb5bb9f71
5
5
  SHA512:
6
- metadata.gz: 745a91a5943da893641b66f9246657695e3ddbfb8713e1d258612d59f628d5680f86c8e069be0530cad1209d9447b7aecd2833d9ee89eefaf3d2a28084fa4a64
7
- data.tar.gz: e7948ddcc1ff1a16ec75a80f4e3c3dbed53037eaac8211eb79df326136f65b15c493b3614ca9f36230548ebfa117af4323c425ac17a7d0b298b71ee2ac65312b
6
+ metadata.gz: 0fbdbcfafab63608945e8a707a7ee2c4f3ffcf6625d30e5cd039f36195b636831eceed2efa387240448c1768465da94af36ce7034ce4d4604b92d9b9eb092c5e
7
+ data.tar.gz: 908f8b44d0149d2464c832558af83a6dc77cc77db7670a729c2054251572b9e5f17df5ac152aa7bb0a7cb5a507c942e386bf746a493eaf571e14daa125b338a4
data/CHANGELOG.md CHANGED
@@ -1,91 +1,31 @@
1
- ## Rails 7.2.3 (October 28, 2025) ##
2
-
3
- * Fixed compatibility with `redis` gem `5.4.1`
4
-
5
- *Jean Boussier*
6
-
7
- * Fixed a possible race condition in `stream_from`.
8
-
9
- *OuYangJinTing*
10
-
11
- * Ensure the Postgresql adapter always use a dedicated connection even during system tests.
12
-
13
- Fix an issue with the Action Cable Postgresql adapter causing deadlock or various weird
14
- pg client error during system tests.
15
-
16
- *Jean Boussier*
17
-
18
-
19
- ## Rails 7.2.2.2 (August 13, 2025) ##
20
-
21
- * No changes.
22
-
23
-
24
- ## Rails 7.2.2.1 (December 10, 2024) ##
1
+ ## Rails 8.1.3 (March 24, 2026) ##
25
2
 
26
3
  * No changes.
27
4
 
28
5
 
29
- ## Rails 7.2.2 (October 30, 2024) ##
6
+ ## Rails 8.1.2.1 (March 23, 2026) ##
30
7
 
31
8
  * No changes.
32
9
 
33
10
 
34
- ## Rails 7.2.1.2 (October 23, 2024) ##
11
+ ## Rails 8.1.2 (January 08, 2026) ##
35
12
 
36
13
  * No changes.
37
14
 
38
15
 
39
- ## Rails 7.2.1.1 (October 15, 2024) ##
16
+ ## Rails 8.1.1 (October 28, 2025) ##
40
17
 
41
18
  * No changes.
42
19
 
43
20
 
44
- ## Rails 7.2.1 (August 22, 2024) ##
45
-
46
- * No changes.
47
-
48
-
49
- ## Rails 7.2.0 (August 09, 2024) ##
50
-
51
- * Bring `ActionCable::Connection::TestCookieJar` in alignment with `ActionDispatch::Cookies::CookieJar` in regards to setting the cookie value.
52
-
53
- Before:
54
-
55
- ```ruby
56
- cookies[:foo] = { value: "bar" }
57
- puts cookies[:foo] # => { value: "bar" }
58
- ```
59
-
60
- After:
61
-
62
- ```ruby
63
- cookies[:foo] = { value: "bar" }
64
- puts cookies[:foo] # => "bar"
65
- ```
66
-
67
- *Justin Ko*
68
-
69
- * Record ping on every Action Cable message.
70
-
71
- Previously only `ping` and `welcome` message types were keeping the connection active.
72
- Now every Action Cable message updates the `pingedAt` value, preventing the connection
73
- from being marked as stale.
74
-
75
- *yauhenininjia*
21
+ ## Rails 8.1.0 (October 22, 2025) ##
76
22
 
77
- * Add two new assertion methods for Action Cable test cases: `assert_has_no_stream`
78
- and `assert_has_no_stream_for`.
23
+ * Allow passing composite channels to `ActionCable::Channel#stream_for` e.g. `stream_for [ group, group.owner ]`
79
24
 
80
- These methods can be used to assert that a stream has been stopped, e.g. via
81
- `stop_stream` or `stop_stream_for`. They complement the already existing
82
- `assert_has_stream` and `assert_has_stream_for` methods.
25
+ *hey-leon*
83
26
 
84
- ```ruby
85
- assert_has_no_stream "messages"
86
- assert_has_no_stream_for User.find(42)
87
- ```
27
+ * Allow setting nil as subscription connection identifier for Redis.
88
28
 
89
- *Sebastian Pöll*, *Junichi Sato*
29
+ *Nguyen Nguyen*
90
30
 
91
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actioncable/CHANGELOG.md) for previous changes.
31
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/actioncable/CHANGELOG.md) for previous changes.
@@ -2,7 +2,6 @@
2
2
 
3
3
  # :markup: markdown
4
4
 
5
- require "set"
6
5
  require "active_support/rescuable"
7
6
  require "active_support/parameter_filter"
8
7
 
@@ -133,7 +132,11 @@ module ActionCable
133
132
  # Except for public instance methods of Base and its ancestors
134
133
  ActionCable::Channel::Base.public_instance_methods(true) +
135
134
  # Be sure to include shadowed public instance methods of this class
136
- public_instance_methods(false)).uniq.map(&:to_s)
135
+ public_instance_methods(false) -
136
+ # Except the internal methods
137
+ internal_methods).uniq
138
+
139
+ methods.map!(&:name)
137
140
  methods.to_set
138
141
  end
139
142
  end
@@ -151,6 +154,10 @@ module ActionCable
151
154
  super
152
155
  clear_action_methods!
153
156
  end
157
+
158
+ def internal_methods
159
+ super
160
+ end
154
161
  end
155
162
 
156
163
  def initialize(connection, identifier, params = {})
@@ -315,7 +322,7 @@ module ActionCable
315
322
  unless subscription_confirmation_sent?
316
323
  logger.debug "#{self.class.name} is transmitting the subscription confirmation"
317
324
 
318
- ActiveSupport::Notifications.instrument("transmit_subscription_confirmation.action_cable", channel_class: self.class.name) do
325
+ ActiveSupport::Notifications.instrument("transmit_subscription_confirmation.action_cable", channel_class: self.class.name, identifier: @identifier) do
319
326
  connection.transmit identifier: @identifier, type: ActionCable::INTERNAL[:message_types][:confirmation]
320
327
  @subscription_confirmation_sent = true
321
328
  end
@@ -330,7 +337,7 @@ module ActionCable
330
337
  def transmit_subscription_rejection
331
338
  logger.debug "#{self.class.name} is transmitting the subscription rejection"
332
339
 
333
- ActiveSupport::Notifications.instrument("transmit_subscription_rejection.action_cable", channel_class: self.class.name) do
340
+ ActiveSupport::Notifications.instrument("transmit_subscription_rejection.action_cable", channel_class: self.class.name, identifier: @identifier) do
334
341
  connection.transmit identifier: @identifier, type: ActionCable::INTERNAL[:message_types][:rejection]
335
342
  end
336
343
  end
@@ -10,19 +10,19 @@ module ActionCable
10
10
  extend ActiveSupport::Concern
11
11
 
12
12
  module ClassMethods
13
- # Broadcast a hash to a unique broadcasting for this `model` in this channel.
14
- def broadcast_to(model, message)
15
- ActionCable.server.broadcast(broadcasting_for(model), message)
13
+ # Broadcast a hash to a unique broadcasting for this array of `broadcastables` in this channel.
14
+ def broadcast_to(broadcastables, message)
15
+ ActionCable.server.broadcast(broadcasting_for(broadcastables), message)
16
16
  end
17
17
 
18
18
  # Returns a unique broadcasting identifier for this `model` in this channel:
19
19
  #
20
20
  # CommentsChannel.broadcasting_for("all") # => "comments:all"
21
21
  #
22
- # You can pass any object as a target (e.g. Active Record model), and it would
22
+ # You can pass an array of objects as a target (e.g. Active Record model), and it would
23
23
  # be serialized into a string under the hood.
24
- def broadcasting_for(model)
25
- serialize_broadcasting([ channel_name, model ])
24
+ def broadcasting_for(broadcastables)
25
+ serialize_broadcasting([ channel_name ] + Array(broadcastables))
26
26
  end
27
27
 
28
28
  private
@@ -39,6 +39,8 @@ module ActionCable
39
39
  extend ActiveSupport::Concern
40
40
  include ActiveSupport::Callbacks
41
41
 
42
+ INTERNAL_METHODS = [:_run_subscribe_callbacks, :_run_unsubscribe_callbacks] # :nodoc:
43
+
42
44
  included do
43
45
  define_callbacks :subscribe
44
46
  define_callbacks :unsubscribe
@@ -70,6 +72,11 @@ module ActionCable
70
72
  set_callback(:unsubscribe, :after, *methods, &block)
71
73
  end
72
74
  alias_method :on_unsubscribe, :after_unsubscribe
75
+
76
+ private
77
+ def internal_methods
78
+ INTERNAL_METHODS
79
+ end
73
80
  end
74
81
  end
75
82
  end
@@ -108,15 +108,15 @@ module ActionCable
108
108
  end
109
109
  end
110
110
 
111
- # Start streaming the pubsub queue for the `model` in this channel. Optionally,
111
+ # Start streaming the pubsub queue for the `broadcastables` in this channel. Optionally,
112
112
  # you can pass a `callback` that'll be used instead of the default of just
113
113
  # transmitting the updates straight to the subscriber.
114
114
  #
115
115
  # Pass `coder: ActiveSupport::JSON` to decode messages as JSON before passing to
116
116
  # the callback. Defaults to `coder: nil` which does no decoding, passes raw
117
117
  # messages.
118
- def stream_for(model, callback = nil, coder: nil, &block)
119
- stream_from(broadcasting_for(model), callback || block, coder: coder)
118
+ def stream_for(broadcastables, callback = nil, coder: nil, &block)
119
+ stream_from(broadcasting_for(broadcastables), callback || block, coder: coder)
120
120
  end
121
121
 
122
122
  # Unsubscribes streams from the named `broadcasting`.
@@ -2,8 +2,6 @@
2
2
 
3
3
  # :markup: markdown
4
4
 
5
- require "set"
6
-
7
5
  module ActionCable
8
6
  module Connection
9
7
  module Identification
@@ -68,6 +68,7 @@ module ActionCable
68
68
  @nio ||= NIO::Selector.new
69
69
 
70
70
  @executor ||= Concurrent::ThreadPoolExecutor.new(
71
+ name: "ActionCable-streamer",
71
72
  min_threads: 1,
72
73
  max_threads: 10,
73
74
  max_queue: 0,
@@ -9,8 +9,8 @@ module ActionCable
9
9
  end
10
10
 
11
11
  module VERSION
12
- MAJOR = 7
13
- MINOR = 2
12
+ MAJOR = 8
13
+ MINOR = 1
14
14
  TINY = 3
15
15
  PRE = nil
16
16
 
@@ -39,45 +39,44 @@ module ActionCable
39
39
  RemoteConnection.new(server, identifier)
40
40
  end
41
41
 
42
- private
43
- # # Action Cable Remote Connection
44
- #
45
- # Represents a single remote connection found via
46
- # `ActionCable.server.remote_connections.where(*)`. Exists solely for the
47
- # purpose of calling #disconnect on that connection.
48
- class RemoteConnection
49
- class InvalidIdentifiersError < StandardError; end
42
+ # # Action Cable Remote Connection
43
+ #
44
+ # Represents a single remote connection found via
45
+ # `ActionCable.server.remote_connections.where(*)`. Exists solely for the
46
+ # purpose of calling #disconnect on that connection.
47
+ class RemoteConnection
48
+ class InvalidIdentifiersError < StandardError; end
50
49
 
51
- include Connection::Identification, Connection::InternalChannel
50
+ include Connection::Identification, Connection::InternalChannel
52
51
 
53
- def initialize(server, ids)
54
- @server = server
55
- set_identifier_instance_vars(ids)
56
- end
52
+ def initialize(server, ids)
53
+ @server = server
54
+ set_identifier_instance_vars(ids)
55
+ end
57
56
 
58
- # Uses the internal channel to disconnect the connection.
59
- def disconnect(reconnect: true)
60
- server.broadcast internal_channel, { type: "disconnect", reconnect: reconnect }
61
- end
57
+ # Uses the internal channel to disconnect the connection.
58
+ def disconnect(reconnect: true)
59
+ server.broadcast internal_channel, { type: "disconnect", reconnect: reconnect }
60
+ end
62
61
 
63
- # Returns all the identifiers that were applied to this connection.
64
- redefine_method :identifiers do
65
- server.connection_identifiers
66
- end
62
+ # Returns all the identifiers that were applied to this connection.
63
+ redefine_method :identifiers do
64
+ server.connection_identifiers
65
+ end
67
66
 
68
- protected
69
- attr_reader :server
67
+ protected
68
+ attr_reader :server
70
69
 
71
- private
72
- def set_identifier_instance_vars(ids)
73
- raise InvalidIdentifiersError unless valid_identifiers?(ids)
74
- ids.each { |k, v| instance_variable_set("@#{k}", v) }
75
- end
70
+ private
71
+ def set_identifier_instance_vars(ids)
72
+ raise InvalidIdentifiersError unless valid_identifiers?(ids)
73
+ ids.each { |k, v| instance_variable_set("@#{k}", v) }
74
+ end
76
75
 
77
- def valid_identifiers?(ids)
78
- keys = ids.keys
79
- identifiers.all? { |id| keys.include?(id) }
80
- end
81
- end
76
+ def valid_identifiers?(ids)
77
+ keys = ids.keys
78
+ identifiers.all? { |id| keys.include?(id) }
79
+ end
80
+ end
82
81
  end
83
82
  end
@@ -21,10 +21,12 @@ module ActionCable
21
21
  # ActionCable.server.broadcast \
22
22
  # "web_notifications_1", { title: "New things!", body: "All that's fit for print" }
23
23
  #
24
- # # Client-side CoffeeScript, which assumes you've already requested the right to send web notifications:
25
- # App.cable.subscriptions.create "WebNotificationsChannel",
26
- # received: (data) ->
27
- # new Notification data['title'], body: data['body']
24
+ # # Client-side JavaScript, which assumes you've already requested the right to send web notifications:
25
+ # App.cable.subscriptions.create("WebNotificationsChannel", {
26
+ # received: function(data) {
27
+ # new Notification(data['title'], { body: data['body'] })
28
+ # }
29
+ # })
28
30
  module Broadcasting
29
31
  # Broadcast a hash directly to a named `broadcasting`. This will later be JSON
30
32
  # encoded.
@@ -20,7 +20,7 @@ module ActionCable
20
20
 
21
21
  def initialize(max_size: 5)
22
22
  @executor = Concurrent::ThreadPoolExecutor.new(
23
- name: "ActionCable",
23
+ name: "ActionCable-server",
24
24
  min_threads: 1,
25
25
  max_threads: max_size,
26
26
  max_queue: 0,
@@ -29,7 +29,8 @@ module ActionCable
29
29
  end
30
30
 
31
31
  def identifier
32
- @server.config.cable[:id] ||= "ActionCable-PID-#{$$}"
32
+ @server.config.cable[:id] = "ActionCable-PID-#{$$}" unless @server.config.cable.key?(:id)
33
+ @server.config.cable[:id]
33
34
  end
34
35
  end
35
36
  end
@@ -59,17 +59,17 @@ module Rails
59
59
  def create_channel_javascript_file
60
60
  channel_js_path = File.join("app/javascript/channels", class_path, "#{file_name}_channel")
61
61
  js_template "javascript/channel", channel_js_path
62
- gsub_file "#{channel_js_path}.js", /\.\/consumer/, "channels/consumer" unless using_js_runtime?
62
+ gsub_file "#{channel_js_path}.js", /\.\/consumer/, "channels/consumer" if using_importmap?
63
63
  end
64
64
 
65
65
  def import_channels_in_javascript_entrypoint
66
66
  append_to_file "app/javascript/application.js",
67
- using_js_runtime? ? %(import "./channels"\n) : %(import "channels"\n)
67
+ using_importmap? ? %(import "channels"\n) : %(import "./channels"\n)
68
68
  end
69
69
 
70
70
  def import_channel_in_javascript_entrypoint
71
71
  append_to_file "app/javascript/channels/index.js",
72
- using_js_runtime? ? %(import "./#{file_name}_channel"\n) : %(import "channels/#{file_name}_channel"\n)
72
+ using_importmap? ? %(import "channels/#{file_name}_channel"\n) : %(import "./#{file_name}_channel"\n)
73
73
  end
74
74
 
75
75
  def install_javascript_dependencies
@@ -105,7 +105,7 @@ pin_all_from "app/javascript/channels", under: "channels"
105
105
  end
106
106
 
107
107
  def using_bun?
108
- # Cannot assume bun.lockb has been generated yet so we look for a file known to
108
+ # Cannot assume Bun lockfile has been generated yet so we look for a file known to
109
109
  # be generated by the jsbundling-rails gem
110
110
  @using_bun ||= using_js_runtime? && root.join("bun.config.js").exist?
111
111
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actioncable
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.3
4
+ version: 8.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pratik Naik
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.2.3
19
+ version: 8.1.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.2.3
26
+ version: 8.1.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.2.3
33
+ version: 8.1.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.2.3
40
+ version: 8.1.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: nio4r
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -153,10 +153,10 @@ licenses:
153
153
  - MIT
154
154
  metadata:
155
155
  bug_tracker_uri: https://github.com/rails/rails/issues
156
- changelog_uri: https://github.com/rails/rails/blob/v7.2.3/actioncable/CHANGELOG.md
157
- documentation_uri: https://api.rubyonrails.org/v7.2.3/
156
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.3/actioncable/CHANGELOG.md
157
+ documentation_uri: https://api.rubyonrails.org/v8.1.3/
158
158
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
159
- source_code_uri: https://github.com/rails/rails/tree/v7.2.3/actioncable
159
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.3/actioncable
160
160
  rubygems_mfa_required: 'true'
161
161
  rdoc_options: []
162
162
  require_paths:
@@ -165,14 +165,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
165
165
  requirements:
166
166
  - - ">="
167
167
  - !ruby/object:Gem::Version
168
- version: 3.1.0
168
+ version: 3.2.0
169
169
  required_rubygems_version: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - ">="
172
172
  - !ruby/object:Gem::Version
173
173
  version: '0'
174
174
  requirements: []
175
- rubygems_version: 3.6.9
175
+ rubygems_version: 4.0.6
176
176
  specification_version: 4
177
177
  summary: WebSocket framework for Rails.
178
178
  test_files: []