actioncable 7.1.3.2 → 8.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -117
  3. data/app/assets/javascripts/action_cable.js +3 -3
  4. data/app/assets/javascripts/actioncable.esm.js +3 -3
  5. data/app/assets/javascripts/actioncable.js +3 -3
  6. data/lib/action_cable/channel/base.rb +100 -89
  7. data/lib/action_cable/channel/broadcasting.rb +25 -18
  8. data/lib/action_cable/channel/callbacks.rb +27 -25
  9. data/lib/action_cable/channel/naming.rb +9 -8
  10. data/lib/action_cable/channel/periodic_timers.rb +7 -7
  11. data/lib/action_cable/channel/streams.rb +77 -64
  12. data/lib/action_cable/channel/test_case.rb +112 -86
  13. data/lib/action_cable/connection/authorization.rb +4 -1
  14. data/lib/action_cable/connection/base.rb +53 -38
  15. data/lib/action_cable/connection/callbacks.rb +20 -18
  16. data/lib/action_cable/connection/client_socket.rb +3 -1
  17. data/lib/action_cable/connection/identification.rb +8 -6
  18. data/lib/action_cable/connection/internal_channel.rb +5 -2
  19. data/lib/action_cable/connection/message_buffer.rb +4 -1
  20. data/lib/action_cable/connection/stream.rb +2 -0
  21. data/lib/action_cable/connection/stream_event_loop.rb +4 -3
  22. data/lib/action_cable/connection/subscriptions.rb +6 -3
  23. data/lib/action_cable/connection/tagged_logger_proxy.rb +7 -4
  24. data/lib/action_cable/connection/test_case.rb +66 -56
  25. data/lib/action_cable/connection/web_socket.rb +10 -8
  26. data/lib/action_cable/deprecator.rb +2 -0
  27. data/lib/action_cable/engine.rb +5 -3
  28. data/lib/action_cable/gem_version.rb +7 -5
  29. data/lib/action_cable/helpers/action_cable_helper.rb +21 -19
  30. data/lib/action_cable/remote_connections.rb +47 -45
  31. data/lib/action_cable/server/base.rb +27 -15
  32. data/lib/action_cable/server/broadcasting.rb +23 -17
  33. data/lib/action_cable/server/configuration.rb +17 -14
  34. data/lib/action_cable/server/connections.rb +11 -5
  35. data/lib/action_cable/server/worker/active_record_connection_management.rb +2 -0
  36. data/lib/action_cable/server/worker.rb +4 -2
  37. data/lib/action_cable/subscription_adapter/async.rb +2 -0
  38. data/lib/action_cable/subscription_adapter/base.rb +2 -0
  39. data/lib/action_cable/subscription_adapter/channel_prefix.rb +2 -0
  40. data/lib/action_cable/subscription_adapter/inline.rb +2 -0
  41. data/lib/action_cable/subscription_adapter/postgresql.rb +7 -6
  42. data/lib/action_cable/subscription_adapter/redis.rb +5 -2
  43. data/lib/action_cable/subscription_adapter/subscriber_map.rb +2 -0
  44. data/lib/action_cable/subscription_adapter/test.rb +8 -5
  45. data/lib/action_cable/test_case.rb +2 -0
  46. data/lib/action_cable/test_helper.rb +51 -52
  47. data/lib/action_cable/version.rb +3 -1
  48. data/lib/action_cable.rb +13 -7
  49. data/lib/rails/generators/channel/channel_generator.rb +4 -2
  50. data/lib/rails/generators/test_unit/channel_generator.rb +2 -0
  51. metadata +16 -16
  52. /data/lib/rails/generators/channel/templates/application_cable/{channel.rb → channel.rb.tt} +0 -0
  53. /data/lib/rails/generators/channel/templates/application_cable/{connection.rb → connection.rb.tt} +0 -0
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support"
4
6
  require "active_support/test_case"
5
7
  require "active_support/core_ext/hash/indifferent_access"
@@ -15,11 +17,10 @@ module ActionCable
15
17
  end
16
18
  end
17
19
 
18
- # = Action Cable \Channel Stub
20
+ # # Action Cable Channel Stub
19
21
  #
20
- # Stub +stream_from+ to track streams for the channel.
21
- # Add public aliases for +subscription_confirmation_sent?+ and
22
- # +subscription_rejected?+.
22
+ # Stub `stream_from` to track streams for the channel. Add public aliases for
23
+ # `subscription_confirmation_sent?` and `subscription_rejected?`.
23
24
  module ChannelStub
24
25
  def confirmed?
25
26
  subscription_confirmation_sent?
@@ -86,103 +87,106 @@ module ActionCable
86
87
 
87
88
  # Superclass for Action Cable channel functional tests.
88
89
  #
89
- # == Basic example
90
+ # ## Basic example
90
91
  #
91
92
  # Functional tests are written as follows:
92
- # 1. First, one uses the +subscribe+ method to simulate subscription creation.
93
- # 2. Then, one asserts whether the current state is as expected. "State" can be anything:
94
- # transmitted messages, subscribed streams, etc.
93
+ # 1. First, one uses the `subscribe` method to simulate subscription creation.
94
+ # 2. Then, one asserts whether the current state is as expected. "State" can be
95
+ # anything: transmitted messages, subscribed streams, etc.
96
+ #
95
97
  #
96
98
  # For example:
97
99
  #
98
- # class ChatChannelTest < ActionCable::Channel::TestCase
99
- # def test_subscribed_with_room_number
100
- # # Simulate a subscription creation
101
- # subscribe room_number: 1
100
+ # class ChatChannelTest < ActionCable::Channel::TestCase
101
+ # def test_subscribed_with_room_number
102
+ # # Simulate a subscription creation
103
+ # subscribe room_number: 1
102
104
  #
103
- # # Asserts that the subscription was successfully created
104
- # assert subscription.confirmed?
105
+ # # Asserts that the subscription was successfully created
106
+ # assert subscription.confirmed?
105
107
  #
106
- # # Asserts that the channel subscribes connection to a stream
107
- # assert_has_stream "chat_1"
108
+ # # Asserts that the channel subscribes connection to a stream
109
+ # assert_has_stream "chat_1"
108
110
  #
109
- # # Asserts that the channel subscribes connection to a specific
110
- # # stream created for a model
111
- # assert_has_stream_for Room.find(1)
112
- # end
111
+ # # Asserts that the channel subscribes connection to a specific
112
+ # # stream created for a model
113
+ # assert_has_stream_for Room.find(1)
114
+ # end
113
115
  #
114
- # def test_does_not_stream_with_incorrect_room_number
115
- # subscribe room_number: -1
116
+ # def test_does_not_stream_with_incorrect_room_number
117
+ # subscribe room_number: -1
116
118
  #
117
- # # Asserts that not streams was started
118
- # assert_no_streams
119
- # end
119
+ # # Asserts that not streams was started
120
+ # assert_no_streams
121
+ # end
120
122
  #
121
- # def test_does_not_subscribe_without_room_number
122
- # subscribe
123
+ # def test_does_not_subscribe_without_room_number
124
+ # subscribe
123
125
  #
124
- # # Asserts that the subscription was rejected
125
- # assert subscription.rejected?
126
+ # # Asserts that the subscription was rejected
127
+ # assert subscription.rejected?
128
+ # end
126
129
  # end
127
- # end
128
130
  #
129
131
  # You can also perform actions:
130
- # def test_perform_speak
131
- # subscribe room_number: 1
132
+ # def test_perform_speak
133
+ # subscribe room_number: 1
132
134
  #
133
- # perform :speak, message: "Hello, Rails!"
135
+ # perform :speak, message: "Hello, Rails!"
134
136
  #
135
- # assert_equal "Hello, Rails!", transmissions.last["text"]
136
- # end
137
+ # assert_equal "Hello, Rails!", transmissions.last["text"]
138
+ # end
139
+ #
140
+ # ## Special methods
141
+ #
142
+ # ActionCable::Channel::TestCase will also automatically provide the following
143
+ # instance methods for use in the tests:
137
144
  #
138
- # == Special methods
145
+ # connection
146
+ # : An ActionCable::Channel::ConnectionStub, representing the current HTTP
147
+ # connection.
139
148
  #
140
- # ActionCable::Channel::TestCase will also automatically provide the following instance
141
- # methods for use in the tests:
149
+ # subscription
150
+ # : An instance of the current channel, created when you call `subscribe`.
142
151
  #
143
- # <b>connection</b>::
144
- # An ActionCable::Channel::ConnectionStub, representing the current HTTP connection.
145
- # <b>subscription</b>::
146
- # An instance of the current channel, created when you call +subscribe+.
147
- # <b>transmissions</b>::
148
- # A list of all messages that have been transmitted into the channel.
152
+ # transmissions
153
+ # : A list of all messages that have been transmitted into the channel.
149
154
  #
150
155
  #
151
- # == Channel is automatically inferred
156
+ # ## Channel is automatically inferred
152
157
  #
153
158
  # ActionCable::Channel::TestCase will automatically infer the channel under test
154
159
  # from the test class name. If the channel cannot be inferred from the test
155
- # class name, you can explicitly set it with +tests+.
160
+ # class name, you can explicitly set it with `tests`.
156
161
  #
157
- # class SpecialEdgeCaseChannelTest < ActionCable::Channel::TestCase
158
- # tests SpecialChannel
159
- # end
160
- #
161
- # == Specifying connection identifiers
162
+ # class SpecialEdgeCaseChannelTest < ActionCable::Channel::TestCase
163
+ # tests SpecialChannel
164
+ # end
162
165
  #
163
- # You need to set up your connection manually to provide values for the identifiers.
164
- # To do this just use:
166
+ # ## Specifying connection identifiers
165
167
  #
166
- # stub_connection(user: users(:john))
168
+ # You need to set up your connection manually to provide values for the
169
+ # identifiers. To do this just use:
167
170
  #
168
- # == Testing broadcasting
171
+ # stub_connection(user: users(:john))
169
172
  #
170
- # ActionCable::Channel::TestCase enhances ActionCable::TestHelper assertions (e.g.
171
- # +assert_broadcasts+) to handle broadcasting to models:
173
+ # ## Testing broadcasting
172
174
  #
175
+ # ActionCable::Channel::TestCase enhances ActionCable::TestHelper assertions
176
+ # (e.g. `assert_broadcasts`) to handle broadcasting to models:
173
177
  #
174
- # # in your channel
175
- # def speak(data)
176
- # broadcast_to room, text: data["message"]
177
- # end
178
+ # # in your channel
179
+ # def speak(data)
180
+ # broadcast_to room, text: data["message"]
181
+ # end
178
182
  #
179
- # def test_speak
180
- # subscribe room_id: rooms(:chat).id
183
+ # def test_speak
184
+ # subscribe room_id: rooms(:chat).id
181
185
  #
182
- # assert_broadcast_on(rooms(:chat), text: "Hello, Rails!") do
183
- # perform :speak, message: "Hello, Rails!"
184
- # end
185
- # end
186
+ # assert_broadcast_on(rooms(:chat), text: "Hello, Rails!") do
187
+ # perform :speak, message: "Hello, Rails!"
188
+ # end
189
+ # end
186
190
  class TestCase < ActiveSupport::TestCase
187
191
  module Behavior
188
192
  extend ActiveSupport::Concern
@@ -231,16 +235,17 @@ module ActionCable
231
235
 
232
236
  # Set up test connection with the specified identifiers:
233
237
  #
234
- # class ApplicationCable < ActionCable::Connection::Base
235
- # identified_by :user, :token
236
- # end
238
+ # class ApplicationCable < ActionCable::Connection::Base
239
+ # identified_by :user, :token
240
+ # end
237
241
  #
238
- # stub_connection(user: users[:john], token: 'my-secret-token')
242
+ # stub_connection(user: users[:john], token: 'my-secret-token')
239
243
  def stub_connection(identifiers = {})
240
244
  @connection = ConnectionStub.new(identifiers)
241
245
  end
242
246
 
243
- # Subscribe to the channel under test. Optionally pass subscription parameters as a Hash.
247
+ # Subscribe to the channel under test. Optionally pass subscription parameters
248
+ # as a Hash.
244
249
  def subscribe(params = {})
245
250
  @connection ||= stub_connection
246
251
  @subscription = self.class.channel_class.new(connection, CHANNEL_IDENTIFIER, params.with_indifferent_access)
@@ -269,8 +274,7 @@ module ActionCable
269
274
  connection.transmissions.filter_map { |data| data["message"] }
270
275
  end
271
276
 
272
- # Enhance TestHelper assertions to handle non-String
273
- # broadcastings
277
+ # Enhance TestHelper assertions to handle non-String broadcastings
274
278
  def assert_broadcasts(stream_or_object, *args)
275
279
  super(broadcasting_for(stream_or_object), *args)
276
280
  end
@@ -281,10 +285,10 @@ module ActionCable
281
285
 
282
286
  # Asserts that no streams have been started.
283
287
  #
284
- # def test_assert_no_started_stream
285
- # subscribe
286
- # assert_no_streams
287
- # end
288
+ # def test_assert_no_started_stream
289
+ # subscribe
290
+ # assert_no_streams
291
+ # end
288
292
  #
289
293
  def assert_no_streams
290
294
  assert subscription.streams.empty?, "No streams started was expected, but #{subscription.streams.count} found"
@@ -292,10 +296,10 @@ module ActionCable
292
296
 
293
297
  # Asserts that the specified stream has been started.
294
298
  #
295
- # def test_assert_started_stream
296
- # subscribe
297
- # assert_has_stream 'messages'
298
- # end
299
+ # def test_assert_started_stream
300
+ # subscribe
301
+ # assert_has_stream 'messages'
302
+ # end
299
303
  #
300
304
  def assert_has_stream(stream)
301
305
  assert subscription.streams.include?(stream), "Stream #{stream} has not been started"
@@ -303,15 +307,37 @@ module ActionCable
303
307
 
304
308
  # Asserts that the specified stream for a model has started.
305
309
  #
306
- # def test_assert_started_stream_for
307
- # subscribe id: 42
308
- # assert_has_stream_for User.find(42)
309
- # end
310
+ # def test_assert_started_stream_for
311
+ # subscribe id: 42
312
+ # assert_has_stream_for User.find(42)
313
+ # end
310
314
  #
311
315
  def assert_has_stream_for(object)
312
316
  assert_has_stream(broadcasting_for(object))
313
317
  end
314
318
 
319
+ # Asserts that the specified stream has not been started.
320
+ #
321
+ # def test_assert_no_started_stream
322
+ # subscribe
323
+ # assert_has_no_stream 'messages'
324
+ # end
325
+ #
326
+ def assert_has_no_stream(stream)
327
+ assert subscription.streams.exclude?(stream), "Stream #{stream} has been started"
328
+ end
329
+
330
+ # Asserts that the specified stream for a model has not started.
331
+ #
332
+ # def test_assert_no_started_stream_for
333
+ # subscribe id: 41
334
+ # assert_has_no_stream_for User.find(42)
335
+ # end
336
+ #
337
+ def assert_has_no_stream_for(object)
338
+ assert_has_no_stream(broadcasting_for(object))
339
+ end
340
+
315
341
  private
316
342
  def check_subscribed!
317
343
  raise "Must be subscribed!" if subscription.nil? || subscription.rejected?
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Connection
5
7
  module Authorization
6
8
  class UnauthorizedError < StandardError; end
7
9
 
8
- # Closes the WebSocket connection if it is open and returns an "unauthorized" reason.
10
+ # Closes the WebSocket connection if it is open and returns an "unauthorized"
11
+ # reason.
9
12
  def reject_unauthorized_connection
10
13
  logger.error "An unauthorized connection attempt was rejected"
11
14
  raise UnauthorizedError
@@ -1,48 +1,57 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch"
4
6
  require "active_support/rescuable"
5
7
 
6
8
  module ActionCable
7
9
  module Connection
8
- # = Action Cable \Connection \Base
10
+ # # Action Cable Connection Base
9
11
  #
10
- # For every WebSocket connection the Action Cable server accepts, a Connection object will be instantiated. This instance becomes the parent
11
- # of all of the channel subscriptions that are created from there on. Incoming messages are then routed to these channel subscriptions
12
- # based on an identifier sent by the Action Cable consumer. The Connection itself does not deal with any specific application logic beyond
13
- # authentication and authorization.
12
+ # For every WebSocket connection the Action Cable server accepts, a Connection
13
+ # object will be instantiated. This instance becomes the parent of all of the
14
+ # channel subscriptions that are created from there on. Incoming messages are
15
+ # then routed to these channel subscriptions based on an identifier sent by the
16
+ # Action Cable consumer. The Connection itself does not deal with any specific
17
+ # application logic beyond authentication and authorization.
14
18
  #
15
19
  # Here's a basic example:
16
20
  #
17
- # module ApplicationCable
18
- # class Connection < ActionCable::Connection::Base
19
- # identified_by :current_user
20
- #
21
- # def connect
22
- # self.current_user = find_verified_user
23
- # logger.add_tags current_user.name
24
- # end
21
+ # module ApplicationCable
22
+ # class Connection < ActionCable::Connection::Base
23
+ # identified_by :current_user
25
24
  #
26
- # def disconnect
27
- # # Any cleanup work needed when the cable connection is cut.
28
- # end
25
+ # def connect
26
+ # self.current_user = find_verified_user
27
+ # logger.add_tags current_user.name
28
+ # end
29
29
  #
30
- # private
31
- # def find_verified_user
32
- # User.find_by_identity(cookies.encrypted[:identity_id]) ||
33
- # reject_unauthorized_connection
30
+ # def disconnect
31
+ # # Any cleanup work needed when the cable connection is cut.
34
32
  # end
33
+ #
34
+ # private
35
+ # def find_verified_user
36
+ # User.find_by_identity(cookies.encrypted[:identity_id]) ||
37
+ # reject_unauthorized_connection
38
+ # end
39
+ # end
35
40
  # end
36
- # end
37
41
  #
38
- # First, we declare that this connection can be identified by its current_user. This allows us to later be able to find all connections
39
- # established for that current_user (and potentially disconnect them). You can declare as many
40
- # identification indexes as you like. Declaring an identification means that an attr_accessor is automatically set for that key.
42
+ # First, we declare that this connection can be identified by its current_user.
43
+ # This allows us to later be able to find all connections established for that
44
+ # current_user (and potentially disconnect them). You can declare as many
45
+ # identification indexes as you like. Declaring an identification means that an
46
+ # attr_accessor is automatically set for that key.
41
47
  #
42
- # Second, we rely on the fact that the WebSocket connection is established with the cookies from the domain being sent along. This makes
43
- # it easy to use signed cookies that were set when logging in via a web interface to authorize the WebSocket connection.
48
+ # Second, we rely on the fact that the WebSocket connection is established with
49
+ # the cookies from the domain being sent along. This makes it easy to use signed
50
+ # cookies that were set when logging in via a web interface to authorize the
51
+ # WebSocket connection.
44
52
  #
45
- # Finally, we add a tag to the connection-specific logger with the name of the current user to easily distinguish their messages in the log.
53
+ # Finally, we add a tag to the connection-specific logger with the name of the
54
+ # current user to easily distinguish their messages in the log.
46
55
  #
47
56
  # Pretty simple, eh?
48
57
  class Base
@@ -69,8 +78,10 @@ module ActionCable
69
78
  @started_at = Time.now
70
79
  end
71
80
 
72
- # Called by the server when a new WebSocket connection is established. This configures the callbacks intended for overwriting by the user.
73
- # This method should not be called directly -- instead rely upon on the #connect (and #disconnect) callbacks.
81
+ # Called by the server when a new WebSocket connection is established. This
82
+ # configures the callbacks intended for overwriting by the user. This method
83
+ # should not be called directly -- instead rely upon on the #connect (and
84
+ # #disconnect) callbacks.
74
85
  def process # :nodoc:
75
86
  logger.info started_request_message
76
87
 
@@ -115,13 +126,15 @@ module ActionCable
115
126
  websocket.close
116
127
  end
117
128
 
118
- # Invoke a method on the connection asynchronously through the pool of thread workers.
129
+ # Invoke a method on the connection asynchronously through the pool of thread
130
+ # workers.
119
131
  def send_async(method, *arguments)
120
132
  worker_pool.async_invoke(self, method, *arguments)
121
133
  end
122
134
 
123
- # Return a basic hash of statistics for the connection keyed with <tt>identifier</tt>, <tt>started_at</tt>, <tt>subscriptions</tt>, and <tt>request_id</tt>.
124
- # This can be returned by a health check against the connection.
135
+ # Return a basic hash of statistics for the connection keyed with `identifier`,
136
+ # `started_at`, `subscriptions`, and `request_id`. This can be returned by a
137
+ # health check against the connection.
125
138
  def statistics
126
139
  {
127
140
  identifier: connection_identifier,
@@ -160,7 +173,8 @@ module ActionCable
160
173
  attr_reader :websocket
161
174
  attr_reader :message_buffer
162
175
 
163
- # The request that initiated the WebSocket connection is available here. This gives access to the environment, cookies, etc.
176
+ # The request that initiated the WebSocket connection is available here. This
177
+ # gives access to the environment, cookies, etc.
164
178
  def request # :doc:
165
179
  @request ||= begin
166
180
  environment = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
@@ -168,7 +182,8 @@ module ActionCable
168
182
  end
169
183
  end
170
184
 
171
- # The cookies of the request that initiated the WebSocket connection. Useful for performing authorization checks.
185
+ # The cookies of the request that initiated the WebSocket connection. Useful for
186
+ # performing authorization checks.
172
187
  def cookies # :doc:
173
188
  request.cookie_jar
174
189
  end
@@ -205,9 +220,8 @@ module ActionCable
205
220
  end
206
221
 
207
222
  def send_welcome_message
208
- # Send welcome message to the internal connection monitor channel.
209
- # This ensures the connection monitor state is reset after a successful
210
- # websocket connection.
223
+ # Send welcome message to the internal connection monitor channel. This ensures
224
+ # the connection monitor state is reset after a successful websocket connection.
211
225
  transmit type: ActionCable::INTERNAL[:message_types][:welcome]
212
226
  end
213
227
 
@@ -238,7 +252,8 @@ module ActionCable
238
252
  [ 404, { Rack::CONTENT_TYPE => "text/plain; charset=utf-8" }, [ "Page not found" ] ]
239
253
  end
240
254
 
241
- # Tags are declared in the server but computed in the connection. This allows us per-connection tailored tags.
255
+ # Tags are declared in the server but computed in the connection. This allows us
256
+ # per-connection tailored tags.
242
257
  def new_tagged_logger
243
258
  TaggedLoggerProxy.new server.logger,
244
259
  tags: server.config.log_tags.map { |tag| tag.respond_to?(:call) ? tag.call(request) : tag.to_s.camelize }
@@ -1,33 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/callbacks"
4
6
 
5
7
  module ActionCable
6
8
  module Connection
7
- # = Action Cable \Connection \Callbacks
9
+ # # Action Cable Connection Callbacks
8
10
  #
9
- # The {before_command}[rdoc-ref:ClassMethods#before_command],
10
- # {after_command}[rdoc-ref:ClassMethods#after_command], and
11
- # {around_command}[rdoc-ref:ClassMethods#around_command] callbacks are
12
- # invoked when sending commands to the client, such as when subscribing,
13
- # unsubscribing, or performing an action.
11
+ # The [before_command](rdoc-ref:ClassMethods#before_command),
12
+ # [after_command](rdoc-ref:ClassMethods#after_command), and
13
+ # [around_command](rdoc-ref:ClassMethods#around_command) callbacks are invoked
14
+ # when sending commands to the client, such as when subscribing, unsubscribing,
15
+ # or performing an action.
14
16
  #
15
- # ==== Example
17
+ # #### Example
16
18
  #
17
- # module ApplicationCable
18
- # class Connection < ActionCable::Connection::Base
19
- # identified_by :user
19
+ # module ApplicationCable
20
+ # class Connection < ActionCable::Connection::Base
21
+ # identified_by :user
20
22
  #
21
- # around_command :set_current_account
23
+ # around_command :set_current_account
22
24
  #
23
- # private
25
+ # private
24
26
  #
25
- # def set_current_account
26
- # # Now all channels could use Current.account
27
- # Current.set(account: user.account) { yield }
28
- # end
29
- # end
30
- # end
27
+ # def set_current_account
28
+ # # Now all channels could use Current.account
29
+ # Current.set(account: user.account) { yield }
30
+ # end
31
+ # end
32
+ # end
31
33
  #
32
34
  module Callbacks
33
35
  extend ActiveSupport::Concern
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "websocket/driver"
4
6
 
5
7
  module ActionCable
@@ -43,7 +45,7 @@ module ActionCable
43
45
 
44
46
  @ready_state = CONNECTING
45
47
 
46
- # The driver calls +env+, +url+, and +write+
48
+ # The driver calls `env`, `url`, and `write`
47
49
  @driver = ::WebSocket::Driver.rack(self, protocols: protocols)
48
50
 
49
51
  @driver.on(:open) { |e| open }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
3
+ # :markup: markdown
4
4
 
5
5
  module ActionCable
6
6
  module Connection
@@ -12,18 +12,20 @@ module ActionCable
12
12
  end
13
13
 
14
14
  module ClassMethods
15
- # Mark a key as being a connection identifier index that can then be used to find the specific connection again later.
16
- # Common identifiers are current_user and current_account, but could be anything, really.
15
+ # Mark a key as being a connection identifier index that can then be used to
16
+ # find the specific connection again later. Common identifiers are current_user
17
+ # and current_account, but could be anything, really.
17
18
  #
18
- # Note that anything marked as an identifier will automatically create a delegate by the same name on any
19
- # channel instances created off the connection.
19
+ # Note that anything marked as an identifier will automatically create a
20
+ # delegate by the same name on any channel instances created off the connection.
20
21
  def identified_by(*identifiers)
21
22
  Array(identifiers).each { |identifier| attr_accessor identifier }
22
23
  self.identifiers += identifiers
23
24
  end
24
25
  end
25
26
 
26
- # Return a single connection identifier that combines the value of all the registered identifiers into a single gid.
27
+ # Return a single connection identifier that combines the value of all the
28
+ # registered identifiers into a single gid.
27
29
  def connection_identifier
28
30
  unless defined? @connection_identifier
29
31
  @connection_identifier = connection_gid identifiers.filter_map { |id| instance_variable_get("@#{id}") }
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Connection
5
- # = Action Cable \InternalChannel
7
+ # # Action Cable InternalChannel
6
8
  #
7
- # Makes it possible for the RemoteConnection to disconnect a specific connection.
9
+ # Makes it possible for the RemoteConnection to disconnect a specific
10
+ # connection.
8
11
  module InternalChannel
9
12
  extend ActiveSupport::Concern
10
13
 
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Connection
5
- # Allows us to buffer messages received from the WebSocket before the Connection has been fully initialized, and is ready to receive them.
7
+ # Allows us to buffer messages received from the WebSocket before the Connection
8
+ # has been fully initialized, and is ready to receive them.
6
9
  class MessageBuffer # :nodoc:
7
10
  def initialize(connection)
8
11
  @connection = connection
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Connection
5
7
  #--
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "nio"
4
6
 
5
7
  module ActionCable
@@ -116,9 +118,8 @@ module ActionCable
116
118
  stream.receive incoming
117
119
  end
118
120
  rescue
119
- # We expect one of EOFError or Errno::ECONNRESET in
120
- # normal operation (when the client goes away). But if
121
- # anything else goes wrong, this is still the best way
121
+ # We expect one of EOFError or Errno::ECONNRESET in normal operation (when the
122
+ # client goes away). But if anything else goes wrong, this is still the best way
122
123
  # to handle it.
123
124
  begin
124
125
  stream.close
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/hash/indifferent_access"
4
6
 
5
7
  module ActionCable
6
8
  module Connection
7
- # = Action Cable \Connection \Subscriptions
9
+ # # Action Cable Connection Subscriptions
8
10
  #
9
- # Collection class for all the channel subscriptions established on a given connection. Responsible for routing incoming commands that arrive on
10
- # the connection to the proper channel.
11
+ # Collection class for all the channel subscriptions established on a given
12
+ # connection. Responsible for routing incoming commands that arrive on the
13
+ # connection to the proper channel.
11
14
  class Subscriptions # :nodoc:
12
15
  def initialize(connection)
13
16
  @connection = connection