websocket-rails/websocket-rails — pull request #208 by moaa (2014-04-23 04:37:27+00:00)
Title: Channel Filtering

### Channel Filters

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

### How to use it

I think it is best to explain by example. 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:

```ruby
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:

```coffeescript
# 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:
```ruby
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:

```ruby
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:
```ruby
#available anywhere in your rails app
WebsocketRails[:some_dynamic_channel].filter_with(WebsocketController)
```

And for dynamic catch all methods:
```ruby
WebsocketRails[:some_dynamic_channel].filter_with(WebsocketController, catch_all: :log_messages)
```