提交 83054373 编写于 作者: N Nick Quaranto

[ci skip] Several ActionCable documentation updates:

* Properly indent code sample in ActionCable::Channel::Streams
* Add a doc comment for #stop_all_streams
* Reformat + add <tt> blocks around code references in ActionCable::Base docs
* Clarify and a little better grammar on ActionCable::RemoteConnections
* Correct indentation and clean up ActionCable::Server::Broadcasting code sample
上级 473f6373
......@@ -32,8 +32,11 @@ module Channel
#
# == Action processing
#
# Unlike Action Controllers, channels do not follow a REST constraint form for its actions. It's a remote-procedure call model. You can
# declare any public method on the channel (optionally taking a data argument), and this method is automatically exposed as callable to the client.
# Unlike subclasses of ActionController::Base, channels do not follow a REST
# constraint form for their actions. Instead, ActionCable operates through a
# remote-procedure call model. You can declare any public method on the
# channel (optionally taking a <tt>data</tt> argument), and this method is
# automatically exposed as callable to the client.
#
# Example:
#
......@@ -60,18 +63,22 @@ module Channel
# end
# end
#
# In this example, subscribed/unsubscribed are not callable methods, as they were already declared in ActionCable::Channel::Base, but #appear/away
# are. #generate_connection_token is also not callable as its a private method. You'll see that appear accepts a data parameter, which it then
# uses as part of its model call. #away does not, it's simply a trigger action.
# In this example, subscribed/unsubscribed are not callable methods, as they
# were already declared in ActionCable::Channel::Base, but <tt>#appear</tt>
# and <tt>#away</tt> are. <tt>#generate_connection_token</tt> is also not
# callable as it's a private method. You'll see that appear accepts a data
# parameter, which it then uses as part of its model call. <tt>#away</tt>
# does not, since it's simply a trigger action.
#
# Also note that in this example, current_user is available because it was marked as an identifying attribute on the connection.
# All such identifiers will automatically create a delegation method of the same name on the channel instance.
# Also note that in this example, <tt>current_user</tt> is available because
# it was marked as an identifying attribute on the connection. All such
# identifiers will automatically create a delegation method of the same name
# on the channel instance.
#
# == Rejecting subscription requests
#
# A channel can reject a subscription request in the #subscribed callback by invoking #reject!
#
# Example:
# A channel can reject a subscription request in the #subscribed callback by
# invoking the #reject method:
#
# class ChatChannel < ApplicationCable::Channel
# def subscribed
......@@ -80,8 +87,10 @@ module Channel
# end
# end
#
# In this example, the subscription will be rejected if the current_user does not have access to the chat room.
# On the client-side, Channel#rejected callback will get invoked when the server rejects the subscription request.
# In this example, the subscription will be rejected if the
# <tt>current_user</tt> does not have access to the chat room. On the
# client-side, the <tt>Channel#rejected</tt> callback will get invoked when
# the server rejects the subscription request.
class Base
include Callbacks
include PeriodicTimers
......
......@@ -41,22 +41,23 @@ module Channel
# Example below shows how you can use this to provide performance introspection in the process:
#
# class ChatChannel < ApplicationCable::Channel
# def subscribed
# @room = Chat::Room[params[:room_number]]
# def subscribed
# @room = Chat::Room[params[:room_number]]
#
# stream_for @room, -> (encoded_message) do
# message = ActiveSupport::JSON.decode(encoded_message)
# stream_for @room, -> (encoded_message) do
# message = ActiveSupport::JSON.decode(encoded_message)
#
# if message['originated_at'].present?
# elapsed_time = (Time.now.to_f - message['originated_at']).round(2)
# if message['originated_at'].present?
# elapsed_time = (Time.now.to_f - message['originated_at']).round(2)
#
# ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing
# logger.info "Message took #{elapsed_time}s to arrive"
# end
# ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing
# logger.info "Message took #{elapsed_time}s to arrive"
# end
#
# transmit message
# end
# end
# transmit message
# end
# end
# end
#
# You can stop streaming from all broadcasts by calling #stop_all_streams.
module Streams
......@@ -90,6 +91,7 @@ def stream_for(model, callback = nil)
stream_from(broadcasting_for([ channel_name, model ]), callback)
end
# Unsubscribes all streams associated with this channel from the pubsub queue.
def stop_all_streams
streams.each do |broadcasting, callback|
pubsub.unsubscribe broadcasting, callback
......
module ActionCable
# If you need to disconnect a given connection, you go through the RemoteConnections. You find the connections you're looking for by
# searching the identifier declared on the connection. Example:
# If you need to disconnect a given connection, you can go through the
# RemoteConnections. You can find the connections you're looking for by
# searching for the identifier declared on the connection. For example:
#
# module ApplicationCable
# class Connection < ActionCable::Connection::Base
......@@ -11,8 +12,9 @@ module ActionCable
#
# ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect
#
# That will disconnect all the connections established for User.find(1) across all servers running on all machines (because it uses
# the internal channel that all these servers are subscribed to).
# This will disconnect all the connections established for
# <tt>User.find(1)</tt> across all servers running on all machines, because
# it uses the internal channel that all these servers are subscribed to.
class RemoteConnections
attr_reader :server
......@@ -25,7 +27,7 @@ def where(identifier)
end
private
# Represents a single remote connection found via ActionCable.server.remote_connections.where(*).
# Represents a single remote connection found via <tt>ActionCable.server.remote_connections.where(*)</tt>.
# Exists for the solely for the purpose of calling #disconnect on that connection.
class RemoteConnection
class InvalidIdentifiersError < StandardError; end
......
......@@ -4,19 +4,19 @@ module Server
# broadcastings are streamed directly to the clients subscribed to the named broadcasting. Let's explain with a full-stack example:
#
# class WebNotificationsChannel < ApplicationCable::Channel
# def subscribed
# stream_from "web_notifications_#{current_user.id}"
# end
# end
# def subscribed
# stream_from "web_notifications_#{current_user.id}"
# end
# end
#
# # Somewhere in your app this is called, perhaps from a NewCommentJob
# ActionCable.server.broadcast \
# "web_notifications_1", { title: 'New things!', body: 'All shit fit for print' }
# # Somewhere in your app this is called, perhaps from a NewCommentJob
# ActionCable.server.broadcast \
# "web_notifications_1", { title: "New things!", body: "All that's fit for print" }
#
# # Client-side coffescript, which assumes you've already requested the right to send web notifications
# App.cable.subscriptions.create "WebNotificationsChannel",
# received: (data) ->
# new Notification data['title'], body: data['body']
# # Client-side CoffeeScript, which assumes you've already requested the right to send web notifications
# App.cable.subscriptions.create "WebNotificationsChannel",
# received: (data) ->
# new Notification data['title'], body: data['body']
module Broadcasting
# Broadcast a hash directly to a named <tt>broadcasting</tt>. It'll automatically be JSON encoded.
def broadcast(broadcasting, message)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册