websocket-rails 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +32 -0
  3. data/Gemfile +2 -1
  4. data/README.md +29 -34
  5. data/lib/assets/javascripts/websocket_rails/abstract_connection.js.coffee +45 -0
  6. data/lib/assets/javascripts/websocket_rails/channel.js.coffee +34 -17
  7. data/lib/assets/javascripts/websocket_rails/event.js.coffee +13 -11
  8. data/lib/assets/javascripts/websocket_rails/http_connection.js.coffee +44 -45
  9. data/lib/assets/javascripts/websocket_rails/main.js +1 -0
  10. data/lib/assets/javascripts/websocket_rails/websocket_connection.js.coffee +20 -34
  11. data/lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee +60 -15
  12. data/lib/generators/websocket_rails/install/templates/websocket_rails.rb +15 -0
  13. data/lib/rails/config/routes.rb +1 -1
  14. data/lib/rails/tasks/websocket_rails.tasks +6 -2
  15. data/lib/websocket_rails/channel.rb +28 -2
  16. data/lib/websocket_rails/channel_manager.rb +16 -0
  17. data/lib/websocket_rails/configuration.rb +26 -1
  18. data/lib/websocket_rails/connection_adapters/http.rb +7 -0
  19. data/lib/websocket_rails/connection_adapters/web_socket.rb +3 -1
  20. data/lib/websocket_rails/connection_manager.rb +1 -1
  21. data/lib/websocket_rails/controller_factory.rb +1 -1
  22. data/lib/websocket_rails/event.rb +9 -2
  23. data/lib/websocket_rails/logging.rb +0 -1
  24. data/lib/websocket_rails/synchronization.rb +11 -7
  25. data/lib/websocket_rails/version.rb +1 -1
  26. data/spec/javascripts/generated/assets/abstract_connection.js +71 -0
  27. data/spec/javascripts/generated/assets/channel.js +58 -34
  28. data/spec/javascripts/generated/assets/event.js +12 -16
  29. data/spec/javascripts/generated/assets/http_connection.js +67 -65
  30. data/spec/javascripts/generated/assets/websocket_connection.js +36 -51
  31. data/spec/javascripts/generated/assets/websocket_rails.js +68 -21
  32. data/spec/javascripts/generated/specs/channel_spec.js +102 -19
  33. data/spec/javascripts/generated/specs/helpers.js +17 -0
  34. data/spec/javascripts/generated/specs/websocket_connection_spec.js +72 -19
  35. data/spec/javascripts/generated/specs/websocket_rails_spec.js +146 -47
  36. data/spec/javascripts/support/jasmine.yml +10 -2
  37. data/spec/javascripts/support/jasmine_helper.rb +38 -0
  38. data/spec/javascripts/websocket_rails/channel_spec.coffee +66 -12
  39. data/spec/javascripts/websocket_rails/event_spec.coffee +7 -7
  40. data/spec/javascripts/websocket_rails/helpers.coffee +6 -0
  41. data/spec/javascripts/websocket_rails/websocket_connection_spec.coffee +53 -15
  42. data/spec/javascripts/websocket_rails/websocket_rails_spec.coffee +108 -25
  43. data/spec/unit/base_controller_spec.rb +41 -0
  44. data/spec/unit/channel_manager_spec.rb +21 -0
  45. data/spec/unit/channel_spec.rb +43 -3
  46. data/spec/unit/connection_adapters/http_spec.rb +24 -3
  47. data/spec/unit/connection_adapters_spec.rb +2 -2
  48. data/spec/unit/connection_manager_spec.rb +1 -1
  49. data/spec/unit/event_spec.rb +25 -1
  50. data/spec/unit/logging_spec.rb +1 -1
  51. metadata +57 -67
  52. data/spec/javascripts/support/jasmine_config.rb +0 -63
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2f431734036d380cfcb865a9db8dd0cb57a8b0e0
4
+ data.tar.gz: 5c68a9bd3f5bffd6ba001521f914c7118613e5f3
5
+ SHA512:
6
+ metadata.gz: 3171366f6a8d400adcfd0b5bcf83baed9abe8d34985122503f49b698002a8842ff5bde5cdd5d4c5b35c39056e01bc8f8a46c812d7cbd4eaa51ffc11c330ffc20
7
+ data.tar.gz: dd0eddf5584f3a22e2f30fd207c83f7355e0ca5351577aedbf074efa597c278fb117d673d308abcbc9bf904a3ccfd5f9a67c4034df386027b110a218c7a9f151
@@ -1,5 +1,37 @@
1
1
  # WebsocketRails Change Log
2
2
 
3
+ ## Version 0.7.0
4
+
5
+ March 14 2014
6
+
7
+ * Add verification of parsing results in Event. (Prevents a possible
8
+ denial of service attack when sending improperly formatted but valid
9
+ JSON. Thanks to @maharifu
10
+
11
+ * Support HTTP streaming for Internet Explorer versions 8+ by using
12
+ XDomainRequest - Thanks to @lkol
13
+
14
+ * Added a possibility to set channel success and failure callbacks on
15
+ subscribe. - Thanks to @lkol
16
+
17
+ * Rescue symbolizing of channel names. fixes #166 - Thanks to @KazW
18
+
19
+ * Refactor *.coffee files. Add reconnect() method. - Thanks to @jtomaszewski
20
+
21
+ * Add Channel tokens to prevent unauthorized subscriptions to channels.
22
+ Thanks - @moaa and @elthariel
23
+
24
+ * Fixed a bug where a newline was being outputted in the log regardless of log level - Thanks to @markmalek
25
+
26
+ * Properly handle WSS and WS protocols in the JavaScript client - Thanks
27
+ to @markee
28
+
29
+ * Defer #on_open to EM.next_tick. fixes #135 - Thanks to @moaa
30
+
31
+ * Add subscriber Join/Part events for channels - Thanks to @moaa
32
+
33
+ * Convert controller's `action_name` to a string to get AbstractController::Callbacks (`before_action`) working properly [fixes #150] - Thanks to @Pitr
34
+
3
35
  ## Version 0.6.2
4
36
 
5
37
  September 8 2013
data/Gemfile CHANGED
@@ -2,11 +2,12 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem "rspec-rails", ">=2.12.0"
5
+ gem "rspec-rails", ">=2.14.0"
6
6
  gem "therubyrhino"
7
7
  gem "therubyracer"
8
8
  gem "jasmine"
9
9
  gem "headless"
10
+ gem "selenium-webdriver"
10
11
  gem "coffee-script"
11
12
  gem "thin"
12
13
  gem "eventmachine"
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Websocket-Rails
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/DanKnox/websocket-rails.png)](https://secure.travis-ci.org/DanKnox/websocket-rails)
3
+ [![Build Status](https://travis-ci.org/websocket-rails/websocket-rails.png?branch=master)](https://travis-ci.org/websocket-rails/websocket-rails)
4
4
 
5
- If you haven't done so yet, check out the [Project Page](http://danknox.github.com/websocket-rails/) to get a feel for the project direction. Feedback is very much appreciated. Post an issue on the issue tracker or [shoot us an email](mailto:support@threedotloft.com) to give us your thoughts.
5
+ If you haven't done so yet, check out the [Project
6
+ Page](http://websocket-rails.github.io) to get a feel for the project direction. Feedback is very much appreciated. Post an issue on the issue tracker or [shoot us an email](mailto:support@threedotloft.com) to give us your thoughts.
6
7
 
7
8
  **Find us on IRC #websocket-rails**
8
9
 
@@ -11,17 +12,10 @@ questions.
11
12
 
12
13
  ## Recent Updates
13
14
 
14
- Check out the [CHANGELOG](https://github.com/DanKnox/websocket-rails/blob/master/CHANGELOG.md) to find out what's new.
15
+ Check out the [CHANGELOG](https://github.com/websocket-rails/websocket-rails/blob/master/CHANGELOG.md) to find out what's new.
15
16
 
16
17
  As of version 0.2.0, non event machine based web servers such as Phusion
17
- Passenger are supported through the use of the [Standalone Server Mode](https://github.com/DanKnox/websocket-rails/wiki/Standalone-Server-Mode).
18
-
19
- **Note About Development**
20
-
21
- I am currently seeking a co-maintainer for this project. My time has
22
- been limited recently and I have not been as attentive to issues and
23
- feature requests as I would like. If you are interested in helping out
24
- please send me an email or post a message on the issue tracker.
18
+ Passenger are supported through the use of the [Standalone Server Mode](https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode).
25
19
 
26
20
  ## Overview
27
21
 
@@ -33,23 +27,21 @@ just about any browser with Flash sockets.
33
27
 
34
28
  ## Installation and Usage Guides
35
29
 
36
- Check out the [Example Application](https://github.com/DanKnox/websocket-rails-Example-Project) for an example implementation.
37
-
38
30
  * [Installation
39
- Guide](https://github.com/DanKnox/websocket-rails/wiki/Installation-and-Setup)
31
+ Guide](https://github.com/websocket-rails/websocket-rails/wiki/Installation-and-Setup)
40
32
  * [Event
41
- Router](https://github.com/DanKnox/websocket-rails/wiki/The-Event-Router)
42
- * [WebsocketRails Controllers](https://github.com/DanKnox/websocket-rails/wiki/WebsocketRails Controllers)
33
+ Router](https://github.com/websocket-rails/websocket-rails/wiki/The-Event-Router)
34
+ * [WebsocketRails Controllers](https://github.com/websocket-rails/websocket-rails/wiki/WebsocketRails Controllers)
43
35
  * [Using the JavaScript
44
- Client](https://github.com/DanKnox/websocket-rails/wiki/Using-the-JavaScript-Client)
36
+ Client](https://github.com/websocket-rails/websocket-rails/wiki/Using-the-JavaScript-Client)
45
37
  * [Using
46
- Channels](https://github.com/DanKnox/websocket-rails/wiki/Working-with-Channels)
47
- * [Using Private Channels](https://github.com/DanKnox/websocket-rails/wiki/Using-Private-Channels)
38
+ Channels](https://github.com/websocket-rails/websocket-rails/wiki/Working-with-Channels)
39
+ * [Using Private Channels](https://github.com/websocket-rails/websocket-rails/wiki/Using-Private-Channels)
48
40
  * [The
49
- DataStore](https://github.com/DanKnox/websocket-rails/wiki/Using-the-DataStore)
50
- * [Reloading Controllers In Development](https://github.com/DanKnox/websocket-rails/wiki/Reloading-Controllers-In-Development)
51
- * [Multiple Servers and Background Jobs](https://github.com/DanKnox/websocket-rails/wiki/Multiple-Servers-and-Background-Jobs)
52
- * [Standalone Server Mode](https://github.com/DanKnox/websocket-rails/wiki/Standalone-Server-Mode)
41
+ DataStore](https://github.com/websocket-rails/websocket-rails/wiki/Using-the-DataStore)
42
+ * [Reloading Controllers In Development](https://github.com/websocket-rails/websocket-rails/wiki/Reloading-Controllers-In-Development)
43
+ * [Multiple Servers and Background Jobs](https://github.com/websocket-rails/websocket-rails/wiki/Multiple-Servers-and-Background-Jobs)
44
+ * [Standalone Server Mode](https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode)
53
45
 
54
46
  ## Handle Events With Class
55
47
 
@@ -211,23 +203,26 @@ WebsocketRails[:secret_posts].make_private
211
203
  On the client side, you can use the `dispatcher.subscribe_private()`
212
204
  method to subscribe to a private channel.
213
205
 
214
- Read the [Private Channel Wiki](https://github.com/DanKnox/websocket-rails/wiki/Using-Private-Channels) for more information on subscribing to
215
- private channels from the JavaScript client and handling the
216
- authorization in your controller.
206
+ Read the [Private Channel Wiki](https://github.com/websocket-rails/websocket-rails/wiki/Using-Private-Channels) for more information on subscribing to private channels from the JavaScript client and handling the authorization in your controller.
217
207
 
218
208
  ## Credit where credit is due
219
209
 
220
- Big thanks to our
221
- [contributors](https://github.com/DanKnox/websocket-rails/graphs/contributors)
222
- who have helped keep this project moving.
210
+ Big thanks to our [contributors](https://github.com/websocket-rails/websocket-rails/graphs/contributors) who have helped keep this project moving.
223
211
 
224
- Special thanks to [@nessche](https://github.com/nessche) who provided the improved routing DSL and
225
- RSpec matcher suite.
212
+ Special thanks to [@nessche](https://github.com/nessche) who provided the improved routing DSL and RSpec matcher suite.
213
+
214
+ The `websocket-rails` organization logo was kindly provided by [Uken Games](http://www.uken.com/).
226
215
 
227
216
  ## Development
228
217
 
229
- This gem is created and maintained by Dan Knox and Kyle Whalen under the MIT License.
218
+ Please check out the [Development Guide](https://github.com/websocket-rails/websocket-rails/wiki/Development) if you are interested in contributing. It should cover everything you need to get up and running.
219
+
220
+ ## Core Team
221
+
222
+ The current `websocket-rails` core team consists of the following individuals:
230
223
 
231
- Brought to you by:
224
+ * [@DanKnox](https://github.com/DanKnox)
225
+ * [@Pitr](https://github.com/pitr)
226
+ * [@moaa](https://github.com/moaa)
232
227
 
233
- Three Dot Loft LLC
228
+ New contributors and pull requests are always welcome.
@@ -0,0 +1,45 @@
1
+ ###
2
+ Abstract Interface for the WebSocketRails client.
3
+ ###
4
+ class WebSocketRails.AbstractConnection
5
+
6
+ constructor: (url, @dispatcher) ->
7
+ @message_queue = []
8
+
9
+ close: ->
10
+
11
+ trigger: (event) ->
12
+ if @dispatcher.state != 'connected'
13
+ @message_queue.push event
14
+ else
15
+ @send_event event
16
+
17
+ send_event: (event) ->
18
+ # Events queued before connecting do not have the correct
19
+ # connection_id set yet. We need to update it before dispatching.
20
+ event.connection_id = @connection_id if @connection_id?
21
+
22
+ # ...
23
+
24
+ on_close: (event) ->
25
+ if @dispatcher && @dispatcher._conn == @
26
+ close_event = new WebSocketRails.Event(['connection_closed', event])
27
+ @dispatcher.state = 'disconnected'
28
+ @dispatcher.dispatch close_event
29
+
30
+ on_error: (event) ->
31
+ if @dispatcher && @dispatcher._conn == @
32
+ error_event = new WebSocketRails.Event(['connection_error', event])
33
+ @dispatcher.state = 'disconnected'
34
+ @dispatcher.dispatch error_event
35
+
36
+ on_message: (event_data) ->
37
+ if @dispatcher && @dispatcher._conn == @
38
+ @dispatcher.new_message event_data
39
+
40
+ setConnectionId: (@connection_id) ->
41
+
42
+ flush_queue: ->
43
+ for event in @message_queue
44
+ @trigger event
45
+ @message_queue = []
@@ -9,39 +9,56 @@ For instance:
9
9
  ###
10
10
  class WebSocketRails.Channel
11
11
 
12
- constructor: (@name,@_dispatcher,@is_private) ->
12
+ constructor: (@name, @_dispatcher, @is_private = false, @on_success, @on_failure) ->
13
+ @_callbacks = {}
14
+ @_token = undefined
15
+ @_queue = []
13
16
  if @is_private
14
17
  event_name = 'websocket_rails.subscribe_private'
15
18
  else
16
19
  event_name = 'websocket_rails.subscribe'
17
20
 
18
- event = new WebSocketRails.Event( [event_name, {data: {channel: @name}},@_dispatcher.connection_id], @_success_launcher, @_failure_launcher)
21
+ @connection_id = @_dispatcher._conn?.connection_id
22
+ event = new WebSocketRails.Event( [event_name, {data: {channel: @name}}, @connection_id], @_success_launcher, @_failure_launcher)
19
23
  @_dispatcher.trigger_event event
20
- @_callbacks = {}
21
24
 
22
- destroy: () =>
23
- event_name = 'websocket_rails.unsubscribe'
24
- event = new WebSocketRails.Event( [event_name, {data: {channel: @name}}, @_dispatcher.connection_id] )
25
- @_dispatcher.trigger_event event
25
+ destroy: ->
26
+ if @connection_id == @_dispatcher._conn?.connection_id
27
+ event_name = 'websocket_rails.unsubscribe'
28
+ event = new WebSocketRails.Event( [event_name, {data: {channel: @name}}, @connection_id] )
29
+ @_dispatcher.trigger_event event
26
30
  @_callbacks = {}
27
31
 
28
- bind: (event_name, callback) =>
32
+ bind: (event_name, callback) ->
29
33
  @_callbacks[event_name] ?= []
30
34
  @_callbacks[event_name].push callback
31
35
 
32
- trigger: (event_name, message) =>
33
- event = new WebSocketRails.Event( [event_name, {channel: @name, data: message}, @_dispatcher.connection_id] )
34
- @_dispatcher.trigger_event event
36
+ trigger: (event_name, message) ->
37
+ event = new WebSocketRails.Event( [event_name, {channel: @name, data: message, token: @_token}, @connection_id] )
38
+ if !@_token
39
+ @_queue.push event
40
+ else
41
+ @_dispatcher.trigger_event event
42
+
43
+ dispatch: (event_name, message) ->
44
+ if event_name == 'websocket_rails.channel_token'
45
+ @connection_id = @_dispatcher._conn?.connection_id
46
+ @_token = message['token']
47
+ @flush_queue()
48
+ else
49
+ return unless @_callbacks[event_name]?
50
+ for callback in @_callbacks[event_name]
51
+ callback message
35
52
 
36
- dispatch: (event_name, message) =>
37
- return unless @_callbacks[event_name]?
38
- for callback in @_callbacks[event_name]
39
- callback message
40
-
41
53
  # using this method because @on_success will not be defined when the constructor is executed
42
54
  _success_launcher: (data) =>
43
55
  @on_success(data) if @on_success?
44
-
56
+
45
57
  # using this method because @on_failure will not be defined when the constructor is executed
46
58
  _failure_launcher: (data) =>
47
59
  @on_failure(data) if @on_failure?
60
+
61
+ flush_queue: ->
62
+ for event in @_queue
63
+ @_dispatcher.trigger_event event
64
+ @_queue = []
@@ -4,37 +4,39 @@ The Event object stores all the relevant event information.
4
4
 
5
5
  class WebSocketRails.Event
6
6
 
7
- constructor: (data,@success_callback,@failure_callback) ->
7
+ constructor: (data, @success_callback, @failure_callback) ->
8
8
  @name = data[0]
9
9
  attr = data[1]
10
10
  if attr?
11
11
  @id = if attr['id']? then attr['id'] else (((1+Math.random())*0x10000)|0)
12
12
  @channel = if attr.channel? then attr.channel
13
13
  @data = if attr.data? then attr.data else attr
14
+ @token = if attr.token? then attr.token
14
15
  @connection_id = data[2]
15
16
  if attr.success?
16
17
  @result = true
17
18
  @success = attr.success
18
19
 
19
- is_channel: =>
20
+ is_channel: ->
20
21
  @channel?
21
22
 
22
- is_result: =>
23
- @result == true
23
+ is_result: ->
24
+ typeof @result != 'undefined'
24
25
 
25
- is_ping: =>
26
+ is_ping: ->
26
27
  @name == 'websocket_rails.ping'
27
28
 
28
- serialize: =>
29
+ serialize: ->
29
30
  JSON.stringify [@name, @attributes()]
30
31
 
31
- attributes: =>
32
+ attributes: ->
32
33
  id: @id,
33
34
  channel: @channel,
34
35
  data: @data
36
+ token: @token
35
37
 
36
- run_callbacks: (success,data) =>
37
- if success == true
38
- @success_callback?(data)
38
+ run_callbacks: (@success, @result) ->
39
+ if @success == true
40
+ @success_callback?(@result)
39
41
  else
40
- @failure_callback?(data)
42
+ @failure_callback?(@result)
@@ -1,67 +1,66 @@
1
1
  ###
2
2
  HTTP Interface for the WebSocketRails client.
3
3
  ###
4
- class WebSocketRails.HttpConnection
5
- httpFactories: -> [
4
+ class WebSocketRails.HttpConnection extends WebSocketRails.AbstractConnection
5
+ connection_type: 'http'
6
+
7
+ _httpFactories: -> [
8
+ -> new XDomainRequest(),
6
9
  -> new XMLHttpRequest(),
7
10
  -> new ActiveXObject("Msxml2.XMLHTTP"),
8
11
  -> new ActiveXObject("Msxml3.XMLHTTP"),
9
12
  -> new ActiveXObject("Microsoft.XMLHTTP")
10
13
  ]
11
14
 
12
- createXMLHttpObject: =>
13
- xmlhttp = false
14
- factories = @httpFactories()
15
- for factory in factories
16
- try
17
- xmlhttp = factory()
18
- catch e
19
- continue
20
- break
21
- xmlhttp
22
-
23
- constructor: (@url, @dispatcher) ->
24
- @_url = @url
25
- @_conn = @createXMLHttpObject()
15
+ constructor: (url, @dispatcher) ->
16
+ super
17
+ @_url = "http://#{url}"
18
+ @_conn = @_createXMLHttpObject()
26
19
  @last_pos = 0
27
- @message_queue = []
28
- @_conn.onreadystatechange = @parse_stream
29
- @_conn.addEventListener("load", @connectionClosed, false)
20
+ try
21
+ @_conn.onreadystatechange = => @_parse_stream()
22
+ @_conn.addEventListener("load", @on_close, false)
23
+ catch e
24
+ @_conn.onprogress = => @_parse_stream()
25
+ @_conn.onload = @on_close
26
+ # set this as 3 always for parse_stream as the object does not have this property at all
27
+ @_conn.readyState = 3
30
28
  @_conn.open "GET", @_url, true
31
29
  @_conn.send()
32
30
 
33
- parse_stream: =>
34
- if @_conn.readyState == 3
35
- data = @_conn.responseText.substring @last_pos
36
- @last_pos = @_conn.responseText.length
37
- data = data.replace( /\]\]\[\[/g, "],[" )
38
- decoded_data = JSON.parse data
39
- @dispatcher.new_message decoded_data
31
+ close: ->
32
+ @_conn.abort()
40
33
 
41
- trigger: (event) =>
42
- if @dispatcher.state != 'connected'
43
- @message_queue.push event
44
- else
45
- @post_data @dispatcher.connection_id, event.serialize()
34
+ send_event: (event) ->
35
+ super
36
+ @_post_data event.serialize()
46
37
 
47
- post_data: (connection_id, payload) ->
38
+ _post_data: (payload) ->
48
39
  $.ajax @_url,
49
40
  type: 'POST'
50
41
  data:
51
- client_id: connection_id
42
+ client_id: @connection_id
52
43
  data: payload
53
44
  success: ->
54
45
 
55
- flush_queue: (connection_id) =>
56
- for event in @message_queue
57
- # Events queued before connecting do not have the correct
58
- # connection_id set yet. We need to update it before dispatching.
59
- if connection_id?
60
- event.connection_id = @dispatcher.connection_id
61
- @trigger event
62
- @message_queue = []
46
+ _createXMLHttpObject: ->
47
+ xmlhttp = false
48
+ factories = @_httpFactories()
49
+ for factory in factories
50
+ try
51
+ xmlhttp = factory()
52
+ catch e
53
+ continue
54
+ break
55
+ xmlhttp
63
56
 
64
- connectionClosed: (event) =>
65
- close_event = new WebSocketRails.Event(['connection_closed', event])
66
- @dispatcher.state = 'disconnected'
67
- @dispatcher.dispatch close_event
57
+ _parse_stream: ->
58
+ if @_conn.readyState == 3
59
+ data = @_conn.responseText.substring @last_pos
60
+ @last_pos = @_conn.responseText.length
61
+ data = data.replace( /\]\]\[\[/g, "],[" )
62
+ try
63
+ event_data = JSON.parse data
64
+ @on_message(event_data)
65
+ catch e
66
+ # just ignore if it cannot be parsed, probably whitespace
@@ -1,5 +1,6 @@
1
1
  //= require ./websocket_rails
2
2
  //= require ./event
3
+ //= require ./abstract_connection
3
4
  //= require ./http_connection
4
5
  //= require ./websocket_connection
5
6
  //= require ./channel