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 +4 -4
- data/CHANGELOG.md +10 -70
- data/lib/action_cable/channel/base.rb +11 -4
- data/lib/action_cable/channel/broadcasting.rb +6 -6
- data/lib/action_cable/channel/callbacks.rb +7 -0
- data/lib/action_cable/channel/streams.rb +3 -3
- data/lib/action_cable/connection/identification.rb +0 -2
- data/lib/action_cable/connection/stream_event_loop.rb +1 -0
- data/lib/action_cable/gem_version.rb +2 -2
- data/lib/action_cable/remote_connections.rb +32 -33
- data/lib/action_cable/server/broadcasting.rb +6 -4
- data/lib/action_cable/server/worker.rb +1 -1
- data/lib/action_cable/subscription_adapter/base.rb +2 -1
- data/lib/rails/generators/channel/channel_generator.rb +4 -4
- metadata +10 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e46234a70b3fa658b532b76c3f49bc9edf8daba673caad218ea165bef8c898ea
|
|
4
|
+
data.tar.gz: 598d01f562938624e0471e330d433a679764d4d4f88fdbdacdbe834eb5bb9f71
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0fbdbcfafab63608945e8a707a7ee2c4f3ffcf6625d30e5cd039f36195b636831eceed2efa387240448c1768465da94af36ce7034ce4d4604b92d9b9eb092c5e
|
|
7
|
+
data.tar.gz: 908f8b44d0149d2464c832558af83a6dc77cc77db7670a729c2054251572b9e5f17df5ac152aa7bb0a7cb5a507c942e386bf746a493eaf571e14daa125b338a4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,91 +1,31 @@
|
|
|
1
|
-
## Rails
|
|
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
|
|
6
|
+
## Rails 8.1.2.1 (March 23, 2026) ##
|
|
30
7
|
|
|
31
8
|
* No changes.
|
|
32
9
|
|
|
33
10
|
|
|
34
|
-
## Rails
|
|
11
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
35
12
|
|
|
36
13
|
* No changes.
|
|
37
14
|
|
|
38
15
|
|
|
39
|
-
## Rails
|
|
16
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
40
17
|
|
|
41
18
|
* No changes.
|
|
42
19
|
|
|
43
20
|
|
|
44
|
-
## Rails
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
29
|
+
*Nguyen Nguyen*
|
|
90
30
|
|
|
91
|
-
Please check [
|
|
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)
|
|
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 `
|
|
14
|
-
def broadcast_to(
|
|
15
|
-
ActionCable.server.broadcast(broadcasting_for(
|
|
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
|
|
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(
|
|
25
|
-
serialize_broadcasting([ channel_name
|
|
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 `
|
|
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(
|
|
119
|
-
stream_from(broadcasting_for(
|
|
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`.
|
|
@@ -39,45 +39,44 @@ module ActionCable
|
|
|
39
39
|
RemoteConnection.new(server, identifier)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class
|
|
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
|
-
|
|
50
|
+
include Connection::Identification, Connection::InternalChannel
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
def initialize(server, ids)
|
|
53
|
+
@server = server
|
|
54
|
+
set_identifier_instance_vars(ids)
|
|
55
|
+
end
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
69
|
-
|
|
67
|
+
protected
|
|
68
|
+
attr_reader :server
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
25
|
-
# App.cable.subscriptions.create
|
|
26
|
-
# received: (data)
|
|
27
|
-
# new Notification
|
|
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.
|
|
@@ -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"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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/
|
|
157
|
-
documentation_uri: https://api.rubyonrails.org/
|
|
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/
|
|
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.
|
|
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:
|
|
175
|
+
rubygems_version: 4.0.6
|
|
176
176
|
specification_version: 4
|
|
177
177
|
summary: WebSocket framework for Rails.
|
|
178
178
|
test_files: []
|