-
Notifications
You must be signed in to change notification settings - Fork 284
Filtering Channel Events
Channel filters give the ability to intercept, modify, or cancel the broadcasting of events that are sent through channels.
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
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
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)