websocket-rails 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +22 -0
- data/Gemfile +4 -0
- data/README.md +66 -159
- data/Rakefile +31 -4
- data/bin/thin-socketrails +16 -1
- data/lib/assets/javascripts/websocket_rails/channel.js.coffee +23 -8
- data/lib/assets/javascripts/websocket_rails/event.js.coffee +40 -0
- data/lib/assets/javascripts/websocket_rails/http_connection.js.coffee +18 -10
- data/lib/assets/javascripts/websocket_rails/main.js +1 -0
- data/lib/assets/javascripts/websocket_rails/websocket_connection.js.coffee +15 -10
- data/lib/assets/javascripts/websocket_rails/websocket_rails.js.coffee +41 -23
- data/lib/websocket-rails.rb +4 -4
- data/lib/websocket_rails/base_controller.rb +61 -29
- data/lib/websocket_rails/channel.rb +14 -5
- data/lib/websocket_rails/channel_manager.rb +3 -1
- data/lib/websocket_rails/connection_adapters.rb +34 -12
- data/lib/websocket_rails/connection_manager.rb +4 -0
- data/lib/websocket_rails/dispatcher.rb +27 -3
- data/lib/websocket_rails/engine.rb +2 -5
- data/lib/websocket_rails/event.rb +87 -42
- data/lib/websocket_rails/event_map.rb +70 -20
- data/lib/websocket_rails/event_queue.rb +4 -0
- data/lib/websocket_rails/internal_events.rb +21 -3
- data/lib/websocket_rails/logging.rb +18 -0
- data/lib/websocket_rails/version.rb +1 -1
- data/spec/dummy/log/test.log +0 -429
- data/spec/integration/connection_manager_spec.rb +3 -5
- data/spec/javascripts/generated/assets/channel.js +98 -0
- data/spec/javascripts/generated/assets/event.js +78 -0
- data/spec/javascripts/generated/assets/http_connection.js +108 -0
- data/spec/javascripts/generated/assets/websocket_connection.js +66 -0
- data/spec/javascripts/generated/assets/websocket_rails.js +180 -0
- data/spec/javascripts/generated/specs/channel_spec.js +66 -0
- data/spec/javascripts/generated/specs/event_spec.js +107 -0
- data/spec/javascripts/generated/specs/websocket_connection_spec.js +117 -0
- data/spec/javascripts/generated/specs/websocket_rails_spec.js +232 -0
- data/spec/javascripts/support/jasmine.yml +44 -0
- data/spec/javascripts/support/jasmine_config.rb +63 -0
- data/spec/javascripts/support/vendor/sinon-1.3.4.js +3555 -0
- data/spec/javascripts/websocket_rails/channel_spec.coffee +51 -0
- data/spec/javascripts/websocket_rails/event_spec.coffee +69 -0
- data/spec/javascripts/websocket_rails/websocket_connection_spec.coffee +86 -0
- data/spec/javascripts/websocket_rails/websocket_rails_spec.coffee +166 -0
- data/spec/support/helper_methods.rb +10 -1
- data/spec/unit/channel_spec.rb +28 -4
- data/spec/unit/connection_adapters_spec.rb +17 -0
- data/spec/unit/connection_manager_spec.rb +1 -1
- data/spec/unit/dispatcher_spec.rb +1 -1
- data/spec/unit/event_spec.rb +15 -11
- metadata +22 -4
@@ -18,9 +18,10 @@ Listening for new events from the server
|
|
18
18
|
###
|
19
19
|
class window.WebSocketRails
|
20
20
|
constructor: (@url, @use_websockets = true) ->
|
21
|
-
@state
|
22
|
-
@callbacks
|
23
|
-
@channels
|
21
|
+
@state = 'connecting'
|
22
|
+
@callbacks = {}
|
23
|
+
@channels = {}
|
24
|
+
@queue = {}
|
24
25
|
|
25
26
|
unless @supports_websockets() and @use_websockets
|
26
27
|
@_conn = new WebSocketRails.HttpConnection url, @
|
@@ -31,21 +32,24 @@ class window.WebSocketRails
|
|
31
32
|
|
32
33
|
new_message: (data) =>
|
33
34
|
for socket_message in data
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@
|
35
|
+
event = new WebSocketRails.Event( socket_message )
|
36
|
+
if event.is_result()
|
37
|
+
@queue[event.id]?.run_callbacks(event.success, event.data)
|
38
|
+
@queue[event.id] = null
|
39
|
+
else if event.is_channel()
|
40
|
+
@dispatch_channel event
|
41
|
+
else if event.is_ping()
|
42
|
+
@pong()
|
38
43
|
else
|
39
|
-
|
40
|
-
message = socket_message[1]
|
41
|
-
@dispatch socket_message...
|
44
|
+
@dispatch event
|
42
45
|
|
43
|
-
if @state == 'connecting' and
|
44
|
-
@connection_established
|
46
|
+
if @state == 'connecting' and event.name == 'client_connected'
|
47
|
+
@connection_established event.data
|
45
48
|
|
46
49
|
connection_established: (data) =>
|
47
50
|
@state = 'connected'
|
48
51
|
@connection_id = data.connection_id
|
52
|
+
@_conn.flush_queue data.connection_id
|
49
53
|
if @on_open?
|
50
54
|
@on_open(data)
|
51
55
|
|
@@ -53,13 +57,19 @@ class window.WebSocketRails
|
|
53
57
|
@callbacks[event_name] ?= []
|
54
58
|
@callbacks[event_name].push callback
|
55
59
|
|
56
|
-
trigger: (event_name, data) =>
|
57
|
-
|
60
|
+
trigger: (event_name, data, success_callback, failure_callback) =>
|
61
|
+
event = new WebSocketRails.Event( [event_name, data, @connection_id], success_callback, failure_callback )
|
62
|
+
@queue[event.id] = event
|
63
|
+
@_conn.trigger event
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
trigger_event: (event) =>
|
66
|
+
@queue[event.id] ?= event # Prevent replacing an event that has callbacks stored
|
67
|
+
@_conn.trigger event
|
68
|
+
|
69
|
+
dispatch: (event) =>
|
70
|
+
return unless @callbacks[event.name]?
|
71
|
+
for callback in @callbacks[event.name]
|
72
|
+
callback event.data
|
63
73
|
|
64
74
|
subscribe: (channel_name) =>
|
65
75
|
unless @channels[channel_name]?
|
@@ -69,13 +79,21 @@ class window.WebSocketRails
|
|
69
79
|
else
|
70
80
|
@channels[channel_name]
|
71
81
|
|
72
|
-
|
73
|
-
|
82
|
+
subscribe_private: (channel_name) =>
|
83
|
+
unless @channels[channel_name]?
|
84
|
+
channel = new WebSocketRails.Channel channel_name, @, true
|
85
|
+
@channels[channel_name] = channel
|
86
|
+
channel
|
87
|
+
else
|
88
|
+
@channels[channel_name]
|
74
89
|
|
75
|
-
dispatch_channel: (
|
76
|
-
return unless @channels[channel]?
|
77
|
-
@channels[channel].dispatch
|
90
|
+
dispatch_channel: (event) =>
|
91
|
+
return unless @channels[event.channel]?
|
92
|
+
@channels[event.channel].dispatch event.name, event.data
|
78
93
|
|
79
94
|
supports_websockets: =>
|
80
95
|
(typeof(WebSocket) == "function" or typeof(WebSocket) == "object")
|
81
96
|
|
97
|
+
pong: =>
|
98
|
+
pong = new WebSocketRails.Event( ['websocket_rails.pong',{},@connection_id] )
|
99
|
+
@_conn.trigger pong
|
data/lib/websocket-rails.rb
CHANGED
@@ -17,7 +17,10 @@ module WebsocketRails
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
LOG_LEVEL = :warn
|
21
|
+
|
22
|
+
require 'websocket_rails/engine'
|
23
|
+
require 'websocket_rails/logging'
|
21
24
|
require 'websocket_rails/connection_manager'
|
22
25
|
require 'websocket_rails/dispatcher'
|
23
26
|
require 'websocket_rails/event'
|
@@ -32,9 +35,6 @@ require 'websocket_rails/connection_adapters'
|
|
32
35
|
require 'websocket_rails/connection_adapters/http'
|
33
36
|
require 'websocket_rails/connection_adapters/web_socket'
|
34
37
|
|
35
|
-
::Thin::Server.send( :remove_const, 'DEFAULT_TIMEOUT' )
|
36
|
-
::Thin::Server.const_set( 'DEFAULT_TIMEOUT', 0 )
|
37
|
-
|
38
38
|
# Exceptions
|
39
39
|
class InvalidConnectionError < StandardError
|
40
40
|
def rack_response
|
@@ -2,10 +2,7 @@ require 'websocket_rails/data_store'
|
|
2
2
|
|
3
3
|
module WebsocketRails
|
4
4
|
# Provides controller helper methods for developing a WebsocketRails controller. Action methods
|
5
|
-
# defined on a WebsocketRails controller can be mapped to events using the {
|
6
|
-
# This class should be sub classed in a user's application, similar to the ApplicationController
|
7
|
-
# in a Rails application. You can create your WebsocketRails controllers in your standard Rails
|
8
|
-
# controllers directory.
|
5
|
+
# defined on a WebsocketRails controller can be mapped to events using the {EventMap} class.
|
9
6
|
#
|
10
7
|
# == Example WebsocketRails controller
|
11
8
|
# class ChatController < WebsocketRails::BaseController
|
@@ -17,8 +14,14 @@ module WebsocketRails
|
|
17
14
|
#
|
18
15
|
# It is best to use the provided {DataStore} to temporarily persist data for each client between
|
19
16
|
# events. Read more about it in the {DataStore} documentation.
|
17
|
+
#
|
18
|
+
#
|
20
19
|
class BaseController
|
21
|
-
|
20
|
+
|
21
|
+
def self.inherited(controller)
|
22
|
+
unloadable controller
|
23
|
+
end
|
24
|
+
|
22
25
|
# Add observers to specific events or the controller in general. This functionality is similar
|
23
26
|
# to the Rails before_filter methods. Observers are stored as Proc objects and have access
|
24
27
|
# to the current controller environment.
|
@@ -42,80 +45,109 @@ module WebsocketRails
|
|
42
45
|
@@observers[:general] << block
|
43
46
|
end
|
44
47
|
end
|
45
|
-
|
48
|
+
|
46
49
|
# Stores the observer Procs for the current controller. See {observe} for details.
|
47
50
|
@@observers = Hash.new {|h,k| h[k] = Array.new}
|
48
|
-
|
51
|
+
|
49
52
|
def initialize
|
50
53
|
@data_store = DataStore.new(self)
|
51
54
|
end
|
52
|
-
|
53
|
-
# Provides direct access to the
|
55
|
+
|
56
|
+
# Provides direct access to the connection object for the client that
|
54
57
|
# initiated the event that is currently being executed.
|
55
58
|
def connection
|
56
59
|
@_event.connection
|
57
60
|
end
|
58
|
-
|
61
|
+
|
59
62
|
# The numerical ID for the client connection that initiated the event. The ID is unique
|
60
63
|
# for each currently active connection but can not be used to associate a client between
|
61
|
-
# multiple connection attempts.
|
64
|
+
# multiple connection attempts.
|
62
65
|
def client_id
|
63
66
|
connection.id
|
64
67
|
end
|
65
|
-
|
68
|
+
|
69
|
+
# The {Event} object that triggered this action.
|
70
|
+
# Find the current event name with event.name
|
71
|
+
# Access the data sent with the event with event.data
|
72
|
+
# Find the event's namespace with event.namespace
|
73
|
+
def event
|
74
|
+
@_event
|
75
|
+
end
|
76
|
+
|
66
77
|
# The current message that was passed from the client when the event was initiated. The
|
67
78
|
# message is typically a standard ruby Hash object. See the README for more information.
|
68
79
|
def message
|
69
80
|
@_event.data
|
70
81
|
end
|
71
82
|
alias_method :data, :message
|
72
|
-
|
83
|
+
|
84
|
+
# Trigger the success callback function attached to the client event that triggered
|
85
|
+
# this action. The object passed to this method will be passed as an argument to
|
86
|
+
# the callback function on the client.
|
87
|
+
def trigger_success(data=nil)
|
88
|
+
event.success = true
|
89
|
+
event.data = data
|
90
|
+
event.trigger
|
91
|
+
end
|
92
|
+
|
93
|
+
# Trigger the failure callback function attached to the client event that triggered
|
94
|
+
# this action. The object passed to this method will be passed as an argument to
|
95
|
+
# the callback function on the client.
|
96
|
+
def trigger_failure(data=nil)
|
97
|
+
event.success = false
|
98
|
+
event.data = data
|
99
|
+
event.trigger
|
100
|
+
end
|
101
|
+
|
102
|
+
def accept_channel(data=nil)
|
103
|
+
channel_name = event.data[:channel]
|
104
|
+
WebsocketRails[channel_name].subscribe connection
|
105
|
+
trigger_success data
|
106
|
+
end
|
107
|
+
|
108
|
+
def deny_channel(data=nil)
|
109
|
+
trigger_failure data
|
110
|
+
end
|
111
|
+
|
73
112
|
# Sends a message to the client that initiated the current event being executed. Messages
|
74
113
|
# are serialized as JSON into a two element Array where the first element is the event
|
75
114
|
# and the second element is the message that was passed, typically a Hash.
|
76
|
-
#
|
77
|
-
# # Will arrive on the client as JSON string like the following:
|
78
|
-
# # ['new_message',{'message': 'new message for the client'}]
|
79
|
-
# message_hash = {:message => 'new message for the client'}
|
80
|
-
# send_message :new_message, message_hash
|
81
115
|
#
|
82
116
|
# To send an event under a namespace, add the `:namespace => :target_namespace` option.
|
83
117
|
#
|
84
|
-
# # Will arrive as: ['product.new_message',{'message': 'new message'}]
|
85
118
|
# send_message :new_message, message_hash, :namespace => :product
|
86
119
|
#
|
87
120
|
# Nested namespaces can be passed as an array like the following:
|
88
121
|
#
|
89
|
-
# # Will arrive as: ['products.glasses.new',{'message': 'new message'}]
|
90
122
|
# send_message :new, message_hash, :namespace => [:products,:glasses]
|
91
123
|
#
|
92
124
|
# See the {EventMap} documentation for more on mapping namespaced actions.
|
93
125
|
def send_message(event_name, message, options={})
|
94
|
-
options.merge! :connection => connection
|
95
|
-
event = Event.new( event_name,
|
126
|
+
options.merge! :connection => connection, :data => message
|
127
|
+
event = Event.new( event_name, options )
|
96
128
|
@_dispatcher.send_message event if @_dispatcher.respond_to?(:send_message)
|
97
129
|
end
|
98
|
-
|
130
|
+
|
99
131
|
# Broadcasts a message to all connected clients. See {#send_message} for message passing details.
|
100
132
|
def broadcast_message(event_name, message, options={})
|
101
|
-
options.merge! :connection => connection
|
102
|
-
event = Event.new( event_name,
|
133
|
+
options.merge! :connection => connection, :data => message
|
134
|
+
event = Event.new( event_name, options )
|
103
135
|
@_dispatcher.broadcast_message event if @_dispatcher.respond_to?(:broadcast_message)
|
104
136
|
end
|
105
137
|
|
106
138
|
def request
|
107
139
|
@_request
|
108
140
|
end
|
109
|
-
|
141
|
+
|
110
142
|
# Provides access to the {DataStore} for the current controller. The {DataStore} provides convenience
|
111
143
|
# methods for keeping track of data associated with active connections. See it's documentation for
|
112
144
|
# more information.
|
113
145
|
def data_store
|
114
146
|
@data_store
|
115
147
|
end
|
116
|
-
|
148
|
+
|
117
149
|
private
|
118
|
-
|
150
|
+
|
119
151
|
# Executes the observers that have been defined for this controller. General observers are executed
|
120
152
|
# first and event specific observers are executed last. Each will be executed in the order that
|
121
153
|
# they have been defined. This method is executed by the {Dispatcher}.
|
@@ -139,6 +171,6 @@ module WebsocketRails
|
|
139
171
|
super
|
140
172
|
end
|
141
173
|
end
|
142
|
-
|
174
|
+
|
143
175
|
end
|
144
176
|
end
|
@@ -5,23 +5,32 @@ module WebsocketRails
|
|
5
5
|
|
6
6
|
def initialize(channel_name)
|
7
7
|
@subscribers = []
|
8
|
-
@name
|
8
|
+
@name = channel_name
|
9
|
+
@private = false
|
9
10
|
end
|
10
11
|
|
11
12
|
def subscribe(connection)
|
12
13
|
@subscribers << connection
|
13
14
|
end
|
14
15
|
|
15
|
-
def trigger(event_name,data
|
16
|
-
|
17
|
-
event = Event.new event_name, data
|
16
|
+
def trigger(event_name,data={})
|
17
|
+
data.merge! :channel => name
|
18
|
+
event = Event.new event_name, data
|
18
19
|
send_data event
|
19
20
|
end
|
20
21
|
|
21
22
|
def trigger_event(event)
|
22
23
|
send_data event
|
23
24
|
end
|
24
|
-
|
25
|
+
|
26
|
+
def make_private
|
27
|
+
@private = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def is_private?
|
31
|
+
@private
|
32
|
+
end
|
33
|
+
|
25
34
|
private
|
26
35
|
|
27
36
|
def send_data(event)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
|
1
3
|
module WebsocketRails
|
2
4
|
|
3
5
|
class << self
|
@@ -17,7 +19,7 @@ module WebsocketRails
|
|
17
19
|
attr_reader :channels
|
18
20
|
|
19
21
|
def initialize
|
20
|
-
@channels =
|
22
|
+
@channels = HashWithIndifferentAccess.new
|
21
23
|
end
|
22
24
|
|
23
25
|
def [](channel)
|
@@ -16,6 +16,8 @@ module WebsocketRails
|
|
16
16
|
|
17
17
|
class Base
|
18
18
|
|
19
|
+
include Logging
|
20
|
+
|
19
21
|
def self.accepts?(env)
|
20
22
|
false
|
21
23
|
end
|
@@ -31,9 +33,11 @@ module WebsocketRails
|
|
31
33
|
@request = request
|
32
34
|
@queue = EventQueue.new
|
33
35
|
@dispatcher = dispatcher
|
36
|
+
@connected = true
|
34
37
|
@delegate = DelegationController.new
|
35
38
|
@delegate.instance_variable_set(:@_env,request.env)
|
36
39
|
@delegate.instance_variable_set(:@_request,request)
|
40
|
+
start_ping_timer
|
37
41
|
end
|
38
42
|
|
39
43
|
def on_open(data=nil)
|
@@ -43,7 +47,8 @@ module WebsocketRails
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def on_message(encoded_data)
|
46
|
-
|
50
|
+
event = Event.new_from_json( encoded_data, self )
|
51
|
+
dispatch event
|
47
52
|
end
|
48
53
|
|
49
54
|
def on_close(data=nil)
|
@@ -61,19 +66,25 @@ module WebsocketRails
|
|
61
66
|
@queue << event
|
62
67
|
end
|
63
68
|
|
69
|
+
attr_accessor :flush_scheduled
|
70
|
+
|
64
71
|
def trigger(event)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
72
|
+
# Uncomment when implementing history queueing with redis
|
73
|
+
#enqueue event
|
74
|
+
#unless flush_scheduled
|
75
|
+
# EM.next_tick { flush; flush_scheduled = false }
|
76
|
+
# flush_scheduled = true
|
77
|
+
#end
|
78
|
+
send "[#{event.serialize}]"
|
70
79
|
end
|
71
80
|
|
72
81
|
def flush
|
82
|
+
count = 1
|
73
83
|
message = "["
|
74
84
|
@queue.flush do |event|
|
75
85
|
message << event.serialize
|
76
|
-
message << "," unless
|
86
|
+
message << "," unless count == @queue.size
|
87
|
+
count += 1
|
77
88
|
end
|
78
89
|
message << "]"
|
79
90
|
send message
|
@@ -105,13 +116,24 @@ module WebsocketRails
|
|
105
116
|
dispatcher.connection_manager.close_connection self
|
106
117
|
end
|
107
118
|
|
108
|
-
|
109
|
-
|
119
|
+
attr_accessor :pong
|
120
|
+
public :pong, :pong=
|
121
|
+
|
122
|
+
def start_ping_timer
|
123
|
+
@pong = true
|
124
|
+
@ping_timer = EM::PeriodicTimer.new(10) do
|
125
|
+
log "ping"
|
126
|
+
if pong == true
|
127
|
+
self.pong = false
|
128
|
+
ping = Event.new_on_ping self
|
129
|
+
trigger ping
|
130
|
+
else
|
131
|
+
@ping_timer.cancel
|
132
|
+
on_error
|
133
|
+
end
|
134
|
+
end
|
110
135
|
end
|
111
136
|
|
112
|
-
def flush_scheduled=(value)
|
113
|
-
@flush_scheduled = value
|
114
|
-
end
|
115
137
|
end
|
116
138
|
|
117
139
|
end
|
@@ -7,6 +7,8 @@ module WebsocketRails
|
|
7
7
|
# incoming WebSocket connections.
|
8
8
|
class ConnectionManager
|
9
9
|
|
10
|
+
include Logging
|
11
|
+
|
10
12
|
SuccessfulResponse = [200,{'Content-Type' => 'text/plain'},['success']].freeze
|
11
13
|
BadRequestResponse = [400,{'Content-Type' => 'text/plain'},['invalid']].freeze
|
12
14
|
ExceptionResponse = [500,{'Content-Type' => 'text/plain'},['exception']].freeze
|
@@ -56,11 +58,13 @@ module WebsocketRails
|
|
56
58
|
def open_connection(request)
|
57
59
|
connection = ConnectionAdapters.establish_connection( request, dispatcher )
|
58
60
|
connections << connection
|
61
|
+
log "Connection opened: #{connection}"
|
59
62
|
connection.rack_response
|
60
63
|
end
|
61
64
|
|
62
65
|
def close_connection(connection)
|
63
66
|
connections.delete connection
|
67
|
+
log "Connection closed: #{connection}"
|
64
68
|
connection = nil
|
65
69
|
end
|
66
70
|
public :close_connection
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module WebsocketRails
|
4
4
|
class Dispatcher
|
5
|
+
|
6
|
+
include Logging
|
5
7
|
|
6
8
|
attr_reader :event_map, :connection_manager
|
7
9
|
|
@@ -21,6 +23,7 @@ module WebsocketRails
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def dispatch(event)
|
26
|
+
log "Event received: #{event.name}"
|
24
27
|
if event.is_channel?
|
25
28
|
WebsocketRails[event.channel].trigger_event event
|
26
29
|
else
|
@@ -38,6 +41,10 @@ module WebsocketRails
|
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
44
|
+
def reload_controllers!
|
45
|
+
@event_map.reload_controllers!
|
46
|
+
end
|
47
|
+
|
41
48
|
private
|
42
49
|
|
43
50
|
def route(event)
|
@@ -47,9 +54,13 @@ module WebsocketRails
|
|
47
54
|
begin
|
48
55
|
controller.instance_variable_set(:@_event,event)
|
49
56
|
controller.send :execute_observers, event.name if controller.respond_to?(:execute_observers)
|
50
|
-
controller.send method if controller.respond_to?(method)
|
51
|
-
rescue Exception =>
|
52
|
-
puts
|
57
|
+
result = controller.send method if controller.respond_to?(method)
|
58
|
+
rescue Exception => ex
|
59
|
+
puts ex.backtrace
|
60
|
+
puts "Application Exception: #{ex}"
|
61
|
+
event.success = false
|
62
|
+
event.data = extract_exception_data ex
|
63
|
+
event.trigger
|
53
64
|
end
|
54
65
|
end
|
55
66
|
end
|
@@ -62,5 +73,18 @@ module WebsocketRails
|
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
76
|
+
def extract_exception_data(ex)
|
77
|
+
case ex
|
78
|
+
when ActiveRecord::RecordInvalid
|
79
|
+
{
|
80
|
+
:record => ex.record.attributes,
|
81
|
+
:errors => ex.record.errors,
|
82
|
+
:full_messages => ex.record.errors.full_messages
|
83
|
+
}
|
84
|
+
else
|
85
|
+
ex if ex.respond_to?(:to_json)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
65
89
|
end
|
66
90
|
end
|
@@ -2,14 +2,11 @@ module WebsocketRails
|
|
2
2
|
|
3
3
|
class Engine < Rails::Engine
|
4
4
|
initializer "websocket_rails.load_app_instance_data" do |app|
|
5
|
+
paths['app/controllers'] = 'app/controllers'
|
5
6
|
WebsocketRails.setup do |config|
|
6
7
|
config.app_root = app.root
|
7
8
|
end
|
8
9
|
app.config.autoload_paths += [File.expand_path("../../lib", __FILE__)]
|
9
10
|
end
|
10
|
-
|
11
|
-
initializer "websocket_rails.load_static_assets" do |app|
|
12
|
-
app.middleware.use ::ActionDispatch::Static, "#{root}/public"
|
13
|
-
end
|
14
11
|
end
|
15
|
-
end
|
12
|
+
end
|