Filtering Channel Events

sebglazebrook edited this page Nov 23, 2014 · 3 revisions

Channel filters give the ability to intercept, modify, or cancel the broadcasting of events that are sent through channels.

How to use it

Lets say you have a chat based application where users can send messages to each other in different channels. But you want to make sure that all messages are logged.

Your controller might look something like this:

class ChatController < WebsocketRails::BaseController

  filter_for_channels :chat_room_one

  def new_message
    # store all messages to the database
    ChatLogger.create({user: current_user, channel: event.channel, message: message})
    
    # we can even alter the event object before it is sent back out
    event[:user_nickname] = current_user.nick_name
  end
end

and your client facing javascript/coffeescript might look something like this:

# create your main objects
dispatcher = new WebSocketRails('localhost:3000/websocket')
public_channel = dispatcher.subscribe('chat_room_one')

# listen for new chat messages
public_channel.bind 'new_message', newMessage()

# when the user clicks the send message button
$('#send_button').on 'click', sendMessage()

sendMessage: ->
    public_channel.trigger('new_message', {'message_body': $("#input_box").val()})

newMessage: (data) ->
    $('#chat_room').append("#{data.user_nickname} : #{data.message_body}")
    

As you can see here filter_for_channels gives us a "choke" point for your channel based messages. You can edit and alter the event object as you wish.

Also, stop_event_propagation! gives us a way to halt the channel event from being triggered back out to connected subscribers.

Lets see how that would work:

Your controller:

class WebsocketController < WebsocketRails::BaseController
  filter_for_channels :chat_room_one
  
  def new_message
    if message[:message_body].contains?('bad words')
      current_user.wash_mouth_out_with(soap)
      ChatLogger.create({user: current_user, channel: event.channel, message: message, bad_words: true})
      stop_event_propagation!
    else
      # continue on like normal
      ChatLogger.create({user: current_user, channel: event.channel, message: message})
      message[:user_nickname] = current_user.nickname
    end
  end
end

Channel Events and how to catch them all

It might be a good idea to catch all events on any given channel.

Your controller might look something like this:

class WebsocketController < WebsocketRails::BaseController
  filter_for_channels :chat_room_one, :catch_all => :log_messages

  def log_messages
    ChatLogger.create({user: current_user, channel: event.channel, message: message})
  end
end

Building your channels dynamically?

No problem, you can assign filters to channels after they're created. Similar to the make_private method:

#available anywhere in your rails app
WebsocketRails[:some_dynamic_channel].filter_with(WebsocketController)

And for dynamic catch all methods:

WebsocketRails[:some_dynamic_channel].filter_with(WebsocketController, :log_messages)
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.