actioncable 7.1.3.4 → 7.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -129
  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 +98 -86
  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 +9 -5
  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 +6 -4
  29. data/lib/action_cable/helpers/action_cable_helper.rb +21 -19
  30. data/lib/action_cable/remote_connections.rb +19 -16
  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 +4 -2
  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 +13 -13
  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,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "set"
4
6
 
5
7
  module ActionCable
@@ -12,18 +14,20 @@ module ActionCable
12
14
  end
13
15
 
14
16
  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.
17
+ # Mark a key as being a connection identifier index that can then be used to
18
+ # find the specific connection again later. Common identifiers are current_user
19
+ # and current_account, but could be anything, really.
17
20
  #
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.
21
+ # Note that anything marked as an identifier will automatically create a
22
+ # delegate by the same name on any channel instances created off the connection.
20
23
  def identified_by(*identifiers)
21
24
  Array(identifiers).each { |identifier| attr_accessor identifier }
22
25
  self.identifiers += identifiers
23
26
  end
24
27
  end
25
28
 
26
- # Return a single connection identifier that combines the value of all the registered identifiers into a single gid.
29
+ # Return a single connection identifier that combines the value of all the
30
+ # registered identifiers into a single gid.
27
31
  def connection_identifier
28
32
  unless defined? @connection_identifier
29
33
  @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