Class: Rage::Cable::Channel

Inherits:
Object
  • Object
show all
Defined in:
lib/rage/cable/channel.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.after_subscribe(action_name = nil, **opts, &block) ⇒ Object

Note:

This callback will be triggered even if the subscription was rejected with the #reject method.

Register a new after_subscribe hook that will be called after the #subscribed method.

Examples:

after_subscribe do
  ...
end
after_subscribe :my_method, unless: :subscription_rejected?


209
210
211
# File 'lib/rage/cable/channel.rb', line 209

def after_subscribe(action_name = nil, **opts, &block)
  add_action(:after_subscribe, action_name, **opts, &block)
end

.after_unsubscribe(action_name = nil, **opts, &block) ⇒ Object

Register a new after_unsubscribe hook that will be called after the #unsubscribed method.



219
220
221
# File 'lib/rage/cable/channel.rb', line 219

def after_unsubscribe(action_name = nil, **opts, &block)
  add_action(:after_unsubscribe, action_name, **opts, &block)
end

.before_subscribe(action_name = nil, **opts, &block) ⇒ Object

Register a new before_subscribe hook that will be called before the #subscribed method.

Examples:

before_subscribe :my_method
before_subscribe do
  ...
end
before_subscribe :my_method, if: -> { ... }


196
197
198
# File 'lib/rage/cable/channel.rb', line 196

def before_subscribe(action_name = nil, **opts, &block)
  add_action(:before_subscribe, action_name, **opts, &block)
end

.before_unsubscribe(action_name = nil, **opts, &block) ⇒ Object

Register a new before_unsubscribe hook that will be called before the #unsubscribed method.



214
215
216
# File 'lib/rage/cable/channel.rb', line 214

def before_unsubscribe(action_name = nil, **opts, &block)
  add_action(:before_unsubscribe, action_name, **opts, &block)
end

.broadcast_to(streamable, data) ⇒ Object

Broadcast data to all the clients subscribed to a channel-local stream.

Examples:

NotificationsChannel.broadcast_to(current_user, { message: "You have a new notification!" })

Parameters:

  • streamable (#id, String, Symbol, Numeric, Array)

    an object that will be used to generate the stream name

  • data (Object)

    the data to send to the clients

Raises:

  • (ArgumentError)

    if the streamable object does not satisfy the type requirements



299
300
301
# File 'lib/rage/cable/channel.rb', line 299

def broadcast_to(streamable, data)
  Rage.cable.broadcast(__stream_name_for(streamable), data)
end

.periodically(method_name = nil, every:, &block) ⇒ Object

Set up a timer to periodically perform a task on the channel. Accepts a method name or a block.

Examples:

periodically every: 3.minutes do
  transmit({ action: :update_count, count: current_count })
end
periodically :update_count, every: 3.minutes

Parameters:

  • method_name (Symbol, nil) (defaults to: nil)

    the name of the method to call

  • every (Integer)

    the calling period in seconds



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/rage/cable/channel.rb', line 267

def periodically(method_name = nil, every:, &block)
  callback_name = if block_given?
    raise ArgumentError, "Pass the `method_name` argument or provide a block, not both" if method_name
    define_tmp_method(block)
  elsif method_name.is_a?(Symbol)
    define_tmp_method(eval("-> { #{method_name} }"))
  else
    raise ArgumentError, "Expected a Symbol method name, got #{method_name.inspect}"
  end

  unless every.is_a?(Numeric) && every > 0
    raise ArgumentError, "Expected every: to be a positive number of seconds, got #{every.inspect}"
  end

  callback = eval("->(channel) { channel.#{callback_name} }")

  if @__periodic_timers.nil?
    @__periodic_timers = []
  elsif @__periodic_timers.frozen?
    @__periodic_timers = @__periodic_timers.dup
  end

  @__periodic_timers << [callback, every]
end

.rescue_from(*klasses, with: nil, &block) ⇒ Object

Register an exception handler.

Examples:

rescue_from StandardError, with: :report_error

private

def report_error(e)
  SomeExternalBugtrackingService.notify(e)
end
rescue_from StandardError do |e|
  SomeExternalBugtrackingService.notify(e)
end

Parameters:

  • klasses (Class, Array<Class>)

    exception classes to watch on

  • with (Symbol) (defaults to: nil)

    the name of a handler method. The method can take one argument, which is the raised exception. Alternatively, you can pass a block, which can also take one argument.



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/rage/cable/channel.rb', line 239

def rescue_from(*klasses, with: nil, &block)
  unless with
    if block_given?
      with = define_tmp_method(block)
    else
      raise ArgumentError, "No handler provided. Pass the `with` keyword argument or provide a block."
    end
  end

  if @__rescue_handlers.nil?
    @__rescue_handlers = []
  elsif @__rescue_handlers.frozen?
    @__rescue_handlers = @__rescue_handlers.dup
  end

  @__rescue_handlers.unshift([klasses, with])
end

Instance Method Details

#broadcast(stream, data) ⇒ Object

Broadcast data to all the clients subscribed to a stream.

Examples:

def subscribed
  broadcast("notifications", { message: "A new member has joined!" })
end

Parameters:

  • stream (String)

    the name of the stream

  • data (Object)

    the data to send to the clients



477
478
479
# File 'lib/rage/cable/channel.rb', line 477

def broadcast(stream, data)
  Rage.cable.broadcast(stream, data)
end

#paramsHash{Symbol=>String,Array,Hash,Numeric,NilClass,TrueClass,FalseClass}

Get the params hash passed in during the subscription process.

Returns:

  • (Hash{Symbol=>String,Array,Hash,Numeric,NilClass,TrueClass,FalseClass})


419
420
421
# File 'lib/rage/cable/channel.rb', line 419

def params
  @__params
end

#rejectObject

Reject the subscription request. The method should only be called during the subscription process (i.e. inside the #subscribed method or before_subscribe/after_subscribe hooks).



425
426
427
# File 'lib/rage/cable/channel.rb', line 425

def reject
  @__subscription_rejected = true
end

#stream_for(streamable) ⇒ Object

Subscribe to a local stream. Local streams are associated with a specific channel instance and can be used to send data to the current channel only.

Examples:

Subscribe to a stream

class NotificationsChannel < Rage::Cable::Channel
  def subscribed
    stream_for current_user
  end
end

Broadcast to the stream

NotificationsChannel.broadcast_to(current_user, { message: "You have a new notification!" })

Parameters:

  • streamable (#id, String, Symbol, Numeric, Array)

    an object that will be used to generate the stream name

Raises:

  • (ArgumentError)

    if the streamable object does not satisfy the type requirements



465
466
467
# File 'lib/rage/cable/channel.rb', line 465

def stream_for(streamable)
  stream_from(self.class.__stream_name_for(streamable))
end

#stream_from(stream) ⇒ Object

Subscribe to a stream global stream. Global streams are not associated with any specific channel instance and can be used to broadcast data to multiple channels at once.

Examples:

Subscribe to a stream

class NotificationsChannel < Rage::Cable::Channel
  def subscribed
    stream_from "notifications"
  end
end

Broadcast to the stream

Rage::Cable.broadcast("notifications", { message: "A new member has joined!" })

Parameters:

  • stream (String)

    the name of the stream

Raises:

  • (ArgumentError)

    if the stream name is not a String



448
449
450
451
# File 'lib/rage/cable/channel.rb', line 448

def stream_from(stream)
  raise ArgumentError, "Stream name must be a String" unless stream.is_a?(String)
  Rage.cable.__protocol.subscribe(@__connection, stream, @__params)
end

#subscribedObject

Called once a client has become a subscriber of the channel.



501
502
# File 'lib/rage/cable/channel.rb', line 501

def subscribed
end

#subscription_rejected?Boolean

Checks whether the #reject method has been called.

Returns:

  • (Boolean)


432
433
434
# File 'lib/rage/cable/channel.rb', line 432

def subscription_rejected?
  !!@__subscription_rejected
end

#transmit(data) ⇒ Object

Transmit data to the current client.

Examples:

def subscribed
  transmit({ message: "Hello!" })
end

Parameters:

  • data (Object)

    the data to send to the client



488
489
490
491
492
493
494
495
496
497
498
# File 'lib/rage/cable/channel.rb', line 488

def transmit(data)
  message = Rage.cable.__protocol.serialize(@__params, data)

  if @__is_subscribing
    # we expect a confirmation message to be sent as a result of a successful subscribe call;
    # this will make sure `transmit` calls send data after the confirmation;
    ::Iodine.defer { @__connection.write(message) }
  else
    @__connection.write(message)
  end
end

#unsubscribedObject

Called once a client unsubscribes from the channel.



505
506
# File 'lib/rage/cable/channel.rb', line 505

def unsubscribed
end