class GraphQL::Streaming::ActionCableSubscriber
A subscriber for a channel-query combo.
@example Subscribe to a query in an ActionCable action, re-evaluating it when things change
# Initialize `context` ahead of time so it can be closed over in the subscription block context = {} context[:subscriber] = GraphQLSubscriber.new(self, query_id) do # Tell the schema how to re-fetch results: context[:current_user].reload MySchema.execute(query_string, context: context, variables: variables) end # Run the query MySchema.execute(query_string, context: context, variables: variables) # detect whether any subscriptions were added context[:subscriber].subscribed?
Constants
- CHANNEL_PREFIX
Public Class Methods
@param [ActionCable::Channel::Base] The channel to push updates to @param [Object] The query who the updates belong to (probably provided by the client) @yield Reruns the query
# File lib/graphql/streaming/action_cable_subscriber.rb, line 27 def initialize(channel, query_id, &query_exec) @channel = channel @query_id = query_id @query_exec = query_exec @subscribed = false @own_streams = [] end
Trigger an event with arguments
@example Trigger post_changed
# First, subscribe with "{ post_changed(id: 1) { title } }" # Then, trigger the event: GraphQL::Streaming::ActionCableSubscriber.trigger(:post_changed, {id: 1})
@param [Symbol] The subscription name to trigger @param [Hash] Arguments to send with the subscription
# File lib/graphql/streaming/action_cable_subscriber.rb, line 44 def self.trigger(subscription_handle, trigger_options = {}) ActionCable.server.broadcast("#{CHANNEL_PREFIX}#{subscription_handle}", trigger_options) end
Public Instance Methods
Tell this subscriber to stop sending patches @return [void]
# File lib/graphql/streaming/action_cable_subscriber.rb, line 72 def close @channel.stop_specific_streams(@own_streams) @own_streams.clear @subscribed = false nil end
Subscribe to event named `subscription_handle`, but only when called with arguments `arguments` @param [String] the event name to subscribe to @param [Hash] the arguments to subscribe to
# File lib/graphql/streaming/action_cable_subscriber.rb, line 52 def register(subscription_handle, arguments) @subscribed = true handle = "#{CHANNEL_PREFIX}#{subscription_handle}" original_args = stringify_hash(arguments) @own_streams << @channel.stream_from(handle) do |trigger_json| trigger_args = JSON.parse(trigger_json) if original_args == trigger_args reevaluate_query end end end
@return [Boolean] True if this subscriber registered any subscriptions
# File lib/graphql/streaming/action_cable_subscriber.rb, line 66 def subscribed? @subscribed end
Private Instance Methods
Re-evaluate the given block and send the result as a patch to the root of the query result
# File lib/graphql/streaming/action_cable_subscriber.rb, line 84 def reevaluate_query payload = { patch: { path: [], value: @query_exec.call, }, query_id: @query_id, } @channel.send_graphql_payload(payload) end
# File lib/graphql/streaming/action_cable_subscriber.rb, line 95 def stringify_hash(value) case value when Hash value.inject({}) { |memo, (k, v)| memo[k.to_s] = stringify_hash(v); memo } when Array value.map { |v| stringify_hash(v) } else value end end