Skip to content

Commit a9573ea

Browse files
authored
Merge pull request rails#51035 from rails/rm-docs-actioncable
Transform actioncable documentation to Markdown
2 parents c730877 + 6fdd31d commit a9573ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+726
-572
lines changed

actioncable/lib/action_cable/channel/base.rb

Lines changed: 98 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,112 @@
11
# frozen_string_literal: true
22

3+
# :markup: markdown
4+
35
require "set"
46
require "active_support/rescuable"
57
require "active_support/parameter_filter"
68

79
module ActionCable
810
module Channel
9-
# = Action Cable \Channel \Base
11+
# # Action Cable Channel Base
1012
#
11-
# The channel provides the basic structure of grouping behavior into logical units when communicating over the WebSocket connection.
12-
# You can think of a channel like a form of controller, but one that's capable of pushing content to the subscriber in addition to simply
13-
# responding to the subscriber's direct requests.
13+
# The channel provides the basic structure of grouping behavior into logical
14+
# units when communicating over the WebSocket connection. You can think of a
15+
# channel like a form of controller, but one that's capable of pushing content
16+
# to the subscriber in addition to simply responding to the subscriber's direct
17+
# requests.
1418
#
15-
# Channel instances are long-lived. A channel object will be instantiated when the cable consumer becomes a subscriber, and then
16-
# lives until the consumer disconnects. This may be seconds, minutes, hours, or even days. That means you have to take special care
17-
# not to do anything silly in a channel that would balloon its memory footprint or whatever. The references are forever, so they won't be released
18-
# as is normally the case with a controller instance that gets thrown away after every request.
19+
# Channel instances are long-lived. A channel object will be instantiated when
20+
# the cable consumer becomes a subscriber, and then lives until the consumer
21+
# disconnects. This may be seconds, minutes, hours, or even days. That means you
22+
# have to take special care not to do anything silly in a channel that would
23+
# balloon its memory footprint or whatever. The references are forever, so they
24+
# won't be released as is normally the case with a controller instance that gets
25+
# thrown away after every request.
1926
#
20-
# Long-lived channels (and connections) also mean you're responsible for ensuring that the data is fresh. If you hold a reference to a user
21-
# record, but the name is changed while that reference is held, you may be sending stale data if you don't take precautions to avoid it.
27+
# Long-lived channels (and connections) also mean you're responsible for
28+
# ensuring that the data is fresh. If you hold a reference to a user record, but
29+
# the name is changed while that reference is held, you may be sending stale
30+
# data if you don't take precautions to avoid it.
2231
#
23-
# The upside of long-lived channel instances is that you can use instance variables to keep reference to objects that future subscriber requests
24-
# can interact with. Here's a quick example:
32+
# The upside of long-lived channel instances is that you can use instance
33+
# variables to keep reference to objects that future subscriber requests can
34+
# interact with. Here's a quick example:
2535
#
26-
# class ChatChannel < ApplicationCable::Channel
27-
# def subscribed
28-
# @room = Chat::Room[params[:room_number]]
29-
# end
36+
# class ChatChannel < ApplicationCable::Channel
37+
# def subscribed
38+
# @room = Chat::Room[params[:room_number]]
39+
# end
3040
#
31-
# def speak(data)
32-
# @room.speak data, user: current_user
41+
# def speak(data)
42+
# @room.speak data, user: current_user
43+
# end
3344
# end
34-
# end
3545
#
36-
# The #speak action simply uses the Chat::Room object that was created when the channel was first subscribed to by the consumer when that
37-
# subscriber wants to say something in the room.
46+
# The #speak action simply uses the Chat::Room object that was created when the
47+
# channel was first subscribed to by the consumer when that subscriber wants to
48+
# say something in the room.
3849
#
39-
# == Action processing
50+
# ## Action processing
4051
#
4152
# Unlike subclasses of ActionController::Base, channels do not follow a RESTful
4253
# constraint form for their actions. Instead, Action Cable operates through a
43-
# remote-procedure call model. You can declare any public method on the
44-
# channel (optionally taking a <tt>data</tt> argument), and this method is
45-
# automatically exposed as callable to the client.
54+
# remote-procedure call model. You can declare any public method on the channel
55+
# (optionally taking a `data` argument), and this method is automatically
56+
# exposed as callable to the client.
4657
#
4758
# Example:
4859
#
49-
# class AppearanceChannel < ApplicationCable::Channel
50-
# def subscribed
51-
# @connection_token = generate_connection_token
52-
# end
53-
#
54-
# def unsubscribed
55-
# current_user.disappear @connection_token
56-
# end
60+
# class AppearanceChannel < ApplicationCable::Channel
61+
# def subscribed
62+
# @connection_token = generate_connection_token
63+
# end
5764
#
58-
# def appear(data)
59-
# current_user.appear @connection_token, on: data['appearing_on']
60-
# end
65+
# def unsubscribed
66+
# current_user.disappear @connection_token
67+
# end
6168
#
62-
# def away
63-
# current_user.away @connection_token
64-
# end
69+
# def appear(data)
70+
# current_user.appear @connection_token, on: data['appearing_on']
71+
# end
6572
#
66-
# private
67-
# def generate_connection_token
68-
# SecureRandom.hex(36)
73+
# def away
74+
# current_user.away @connection_token
6975
# end
70-
# end
7176
#
72-
# In this example, the subscribed and unsubscribed methods are not callable methods, as they
73-
# were already declared in ActionCable::Channel::Base, but <tt>#appear</tt>
74-
# and <tt>#away</tt> are. <tt>#generate_connection_token</tt> is also not
75-
# callable, since it's a private method. You'll see that appear accepts a data
76-
# parameter, which it then uses as part of its model call. <tt>#away</tt>
77-
# does not, since it's simply a trigger action.
77+
# private
78+
# def generate_connection_token
79+
# SecureRandom.hex(36)
80+
# end
81+
# end
82+
#
83+
# In this example, the subscribed and unsubscribed methods are not callable
84+
# methods, as they were already declared in ActionCable::Channel::Base, but
85+
# `#appear` and `#away` are. `#generate_connection_token` is also not callable,
86+
# since it's a private method. You'll see that appear accepts a data parameter,
87+
# which it then uses as part of its model call. `#away` does not, since it's
88+
# simply a trigger action.
7889
#
79-
# Also note that in this example, <tt>current_user</tt> is available because
80-
# it was marked as an identifying attribute on the connection. All such
81-
# identifiers will automatically create a delegation method of the same name
82-
# on the channel instance.
90+
# Also note that in this example, `current_user` is available because it was
91+
# marked as an identifying attribute on the connection. All such identifiers
92+
# will automatically create a delegation method of the same name on the channel
93+
# instance.
8394
#
84-
# == Rejecting subscription requests
95+
# ## Rejecting subscription requests
8596
#
8697
# A channel can reject a subscription request in the #subscribed callback by
8798
# invoking the #reject method:
8899
#
89-
# class ChatChannel < ApplicationCable::Channel
90-
# def subscribed
91-
# @room = Chat::Room[params[:room_number]]
92-
# reject unless current_user.can_access?(@room)
100+
# class ChatChannel < ApplicationCable::Channel
101+
# def subscribed
102+
# @room = Chat::Room[params[:room_number]]
103+
# reject unless current_user.can_access?(@room)
104+
# end
93105
# end
94-
# end
95106
#
96-
# In this example, the subscription will be rejected if the
97-
# <tt>current_user</tt> does not have access to the chat room. On the
98-
# client-side, the <tt>Channel#rejected</tt> callback will get invoked when
99-
# the server rejects the subscription request.
107+
# In this example, the subscription will be rejected if the `current_user` does
108+
# not have access to the chat room. On the client-side, the `Channel#rejected`
109+
# callback will get invoked when the server rejects the subscription request.
100110
class Base
101111
include Callbacks
102112
include PeriodicTimers
@@ -109,14 +119,13 @@ class Base
109119
delegate :logger, to: :connection
110120

111121
class << self
112-
# A list of method names that should be considered actions. This
113-
# includes all public instance methods on a channel, less
114-
# any internal methods (defined on Base), adding back in
115-
# any methods that are internal, but still exist on the class
116-
# itself.
122+
# A list of method names that should be considered actions. This includes all
123+
# public instance methods on a channel, less any internal methods (defined on
124+
# Base), adding back in any methods that are internal, but still exist on the
125+
# class itself.
117126
#
118-
# ==== Returns
119-
# * <tt>Set</tt> - A set of all methods that should be considered actions.
127+
# #### Returns
128+
# * `Set` - A set of all methods that should be considered actions.
120129
def action_methods
121130
@action_methods ||= begin
122131
# All public instance methods of this class, including ancestors
@@ -130,9 +139,9 @@ def action_methods
130139
end
131140

132141
private
133-
# action_methods are cached and there is sometimes need to refresh
134-
# them. ::clear_action_methods! allows you to do that, so next time
135-
# you run action_methods, they will be recalculated.
142+
# action_methods are cached and there is sometimes need to refresh them.
143+
# ::clear_action_methods! allows you to do that, so next time you run
144+
# action_methods, they will be recalculated.
136145
def clear_action_methods! # :doc:
137146
@action_methods = nil
138147
end
@@ -161,9 +170,9 @@ def initialize(connection, identifier, params = {})
161170
delegate_connection_identifiers
162171
end
163172

164-
# Extract the action name from the passed data and process it via the channel. The process will ensure
165-
# that the action requested is a public method on the channel declared by the user (so not one of the callbacks
166-
# like #subscribed).
173+
# Extract the action name from the passed data and process it via the channel.
174+
# The process will ensure that the action requested is a public method on the
175+
# channel declared by the user (so not one of the callbacks like #subscribed).
167176
def perform_action(data)
168177
action = extract_action(data)
169178

@@ -177,8 +186,8 @@ def perform_action(data)
177186
end
178187
end
179188

180-
# This method is called after subscription has been added to the connection
181-
# and confirms or rejects the subscription.
189+
# This method is called after subscription has been added to the connection and
190+
# confirms or rejects the subscription.
182191
def subscribe_to_channel
183192
run_callbacks :subscribe do
184193
subscribed
@@ -188,29 +197,32 @@ def subscribe_to_channel
188197
ensure_confirmation_sent
189198
end
190199

191-
# Called by the cable connection when it's cut, so the channel has a chance to cleanup with callbacks.
192-
# This method is not intended to be called directly by the user. Instead, override the #unsubscribed callback.
200+
# Called by the cable connection when it's cut, so the channel has a chance to
201+
# cleanup with callbacks. This method is not intended to be called directly by
202+
# the user. Instead, override the #unsubscribed callback.
193203
def unsubscribe_from_channel # :nodoc:
194204
run_callbacks :unsubscribe do
195205
unsubscribed
196206
end
197207
end
198208

199209
private
200-
# Called once a consumer has become a subscriber of the channel. Usually the place to set up any streams
201-
# you want this channel to be sending to the subscriber.
210+
# Called once a consumer has become a subscriber of the channel. Usually the
211+
# place to set up any streams you want this channel to be sending to the
212+
# subscriber.
202213
def subscribed # :doc:
203214
# Override in subclasses
204215
end
205216

206-
# Called once a consumer has cut its cable connection. Can be used for cleaning up connections or marking
207-
# users as offline or the like.
217+
# Called once a consumer has cut its cable connection. Can be used for cleaning
218+
# up connections or marking users as offline or the like.
208219
def unsubscribed # :doc:
209220
# Override in subclasses
210221
end
211222

212-
# Transmit a hash of data to the subscriber. The hash will automatically be wrapped in a JSON envelope with
213-
# the proper channel identifier marked as the recipient.
223+
# Transmit a hash of data to the subscriber. The hash will automatically be
224+
# wrapped in a JSON envelope with the proper channel identifier marked as the
225+
# recipient.
214226
def transmit(data, via: nil) # :doc:
215227
logger.debug do
216228
status = "#{self.class.name} transmitting #{data.inspect.truncate(300)}"

actioncable/lib/action_cable/channel/broadcasting.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
# :markup: markdown
4+
35
require "active_support/core_ext/object/to_param"
46

57
module ActionCable
@@ -8,17 +10,17 @@ module Broadcasting
810
extend ActiveSupport::Concern
911

1012
module ClassMethods
11-
# Broadcast a hash to a unique broadcasting for this <tt>model</tt> in this channel.
13+
# Broadcast a hash to a unique broadcasting for this `model` in this channel.
1214
def broadcast_to(model, message)
1315
ActionCable.server.broadcast(broadcasting_for(model), message)
1416
end
1517

16-
# Returns a unique broadcasting identifier for this <tt>model</tt> in this channel:
18+
# Returns a unique broadcasting identifier for this `model` in this channel:
1719
#
18-
# CommentsChannel.broadcasting_for("all") # => "comments:all"
20+
# CommentsChannel.broadcasting_for("all") # => "comments:all"
1921
#
20-
# You can pass any object as a target (e.g. Active Record model), and it
21-
# would be serialized into a string under the hood.
22+
# You can pass any object as a target (e.g. Active Record model), and it would
23+
# be serialized into a string under the hood.
2224
def broadcasting_for(model)
2325
serialize_broadcasting([ channel_name, model ])
2426
end

actioncable/lib/action_cable/channel/callbacks.rb

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,39 @@
11
# frozen_string_literal: true
22

3+
# :markup: markdown
4+
35
require "active_support/callbacks"
46

57
module ActionCable
68
module Channel
7-
# = Action Cable \Channel \Callbacks
9+
# # Action Cable Channel Callbacks
10+
#
11+
# Action Cable Channel provides callback hooks that are invoked during the life
12+
# cycle of a channel:
813
#
9-
# Action Cable Channel provides callback hooks that are invoked during the
10-
# life cycle of a channel:
14+
# * [before_subscribe](rdoc-ref:ClassMethods#before_subscribe)
15+
# * [after_subscribe](rdoc-ref:ClassMethods#after_subscribe) (aliased as
16+
# [on_subscribe](rdoc-ref:ClassMethods#on_subscribe))
17+
# * [before_unsubscribe](rdoc-ref:ClassMethods#before_unsubscribe)
18+
# * [after_unsubscribe](rdoc-ref:ClassMethods#after_unsubscribe) (aliased as
19+
# [on_unsubscribe](rdoc-ref:ClassMethods#on_unsubscribe))
1120
#
12-
# * {before_subscribe}[rdoc-ref:ClassMethods#before_subscribe]
13-
# * {after_subscribe}[rdoc-ref:ClassMethods#after_subscribe] (aliased as
14-
# {on_subscribe}[rdoc-ref:ClassMethods#on_subscribe])
15-
# * {before_unsubscribe}[rdoc-ref:ClassMethods#before_unsubscribe]
16-
# * {after_unsubscribe}[rdoc-ref:ClassMethods#after_unsubscribe] (aliased as
17-
# {on_unsubscribe}[rdoc-ref:ClassMethods#on_unsubscribe])
1821
#
19-
# ==== Example
22+
# #### Example
2023
#
21-
# class ChatChannel < ApplicationCable::Channel
22-
# after_subscribe :send_welcome_message, unless: :subscription_rejected?
23-
# after_subscribe :track_subscription
24+
# class ChatChannel < ApplicationCable::Channel
25+
# after_subscribe :send_welcome_message, unless: :subscription_rejected?
26+
# after_subscribe :track_subscription
2427
#
25-
# private
26-
# def send_welcome_message
27-
# broadcast_to(...)
28-
# end
28+
# private
29+
# def send_welcome_message
30+
# broadcast_to(...)
31+
# end
2932
#
30-
# def track_subscription
31-
# # ...
32-
# end
33-
# end
33+
# def track_subscription
34+
# # ...
35+
# end
36+
# end
3437
#
3538
module Callbacks
3639
extend ActiveSupport::Concern
@@ -46,14 +49,13 @@ def before_subscribe(*methods, &block)
4649
set_callback(:subscribe, :before, *methods, &block)
4750
end
4851

49-
# This callback will be triggered after the Base#subscribed method is
50-
# called, even if the subscription was rejected with the Base#reject
51-
# method.
52+
# This callback will be triggered after the Base#subscribed method is called,
53+
# even if the subscription was rejected with the Base#reject method.
5254
#
5355
# To trigger the callback only on successful subscriptions, use the
5456
# Base#subscription_rejected? method:
5557
#
56-
# after_subscribe :my_method, unless: :subscription_rejected?
58+
# after_subscribe :my_method, unless: :subscription_rejected?
5759
#
5860
def after_subscribe(*methods, &block)
5961
set_callback(:subscribe, :after, *methods, &block)

0 commit comments

Comments
 (0)