websocket-rails 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|