ratchetio 0.5.2 → 0.5.3
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/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +3 -0
- data/README.md +10 -0
- data/THANKS +1 -0
- data/lib/ratchetio/version.rb +1 -1
- data/lib/ratchetio.rb +63 -34
- data/spec/dummyapp/app/controllers/home_controller.rb +1 -1
- data/spec/ratchetio_spec.rb +59 -42
- metadata +1 -1
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
**0.5.3**
|
4
|
+
- Add `Ratchetio.silenced`; which allows disabling reporting for a given block. See README for usage.
|
5
|
+
|
3
6
|
**0.5.2**
|
4
7
|
- Fix compat issue with delayed_job below version 3. Exceptions raised by delayed_job below version 3 will not be automatically caught; upgrade to v3 or catch and report by hand.
|
5
8
|
|
data/README.md
CHANGED
@@ -94,6 +94,16 @@ By default, all exceptions reported through `Ratchetio.report_exception()` are r
|
|
94
94
|
If you'd like to customize this list, see the example code in `config/initializers/ratchetio.rb`. Supported levels: "critical", "error", "warning", "info", "debug", "ignore". Set to "ignore" to cause the exception not to be reported at all.
|
95
95
|
|
96
96
|
|
97
|
+
## Silencing exceptions at runtime
|
98
|
+
|
99
|
+
If you just want to disable exception reporting for a single block, use `Ratchetio.silenced`:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
Ratchetio.silenced {
|
103
|
+
foo = bar # will not be reported
|
104
|
+
}
|
105
|
+
```
|
106
|
+
|
97
107
|
|
98
108
|
## Asynchronous reporting
|
99
109
|
|
data/THANKS
CHANGED
data/lib/ratchetio/version.rb
CHANGED
data/lib/ratchetio.rb
CHANGED
@@ -15,9 +15,9 @@ require 'ratchetio/version'
|
|
15
15
|
module Ratchetio
|
16
16
|
class << self
|
17
17
|
attr_writer :configuration
|
18
|
-
|
18
|
+
|
19
19
|
# Configures the gem.
|
20
|
-
#
|
20
|
+
#
|
21
21
|
# Call on app startup to set the `access_token` (required) and other config params.
|
22
22
|
# In a Rails app, this is called by `config/initializers/ratchetio.rb` which is generated
|
23
23
|
# with `rails generate ratchetio access-token-here`
|
@@ -29,7 +29,7 @@ module Ratchetio
|
|
29
29
|
def configure
|
30
30
|
yield(configuration)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def reconfigure
|
34
34
|
@configuration = Configuration.new
|
35
35
|
yield(configuration)
|
@@ -52,7 +52,7 @@ module Ratchetio
|
|
52
52
|
# end
|
53
53
|
#
|
54
54
|
# @param exception [Exception] The exception object to report
|
55
|
-
# @param request_data [Hash] Data describing the request. Should be the result of calling
|
55
|
+
# @param request_data [Hash] Data describing the request. Should be the result of calling
|
56
56
|
# `ratchetio_request_data`.
|
57
57
|
# @param person_data [Hash] Data describing the affected person. Should be the result of calling
|
58
58
|
# `ratchetio_person_data`
|
@@ -61,13 +61,11 @@ module Ratchetio
|
|
61
61
|
return
|
62
62
|
end
|
63
63
|
|
64
|
-
|
65
|
-
if filtered_level == 'ignore'
|
66
|
-
# ignored - do nothing
|
64
|
+
if ignored?(exception)
|
67
65
|
return
|
68
66
|
end
|
69
67
|
|
70
|
-
data = exception_data(exception, filtered_level)
|
68
|
+
data = exception_data(exception, filtered_level(exception))
|
71
69
|
data[:request] = request_data if request_data
|
72
70
|
data[:person] = person_data if person_data
|
73
71
|
|
@@ -84,17 +82,17 @@ module Ratchetio
|
|
84
82
|
# @example
|
85
83
|
# Ratchetio.report_message("User login failed", 'info', :user_id => 123)
|
86
84
|
#
|
87
|
-
# @param message [String] The message body. This will be used to identify the message within
|
88
|
-
# Ratchet. For best results, avoid putting variables in the message body; pass them as
|
89
|
-
# `extra_data` instead.
|
85
|
+
# @param message [String] The message body. This will be used to identify the message within
|
86
|
+
# Ratchet. For best results, avoid putting variables in the message body; pass them as
|
87
|
+
# `extra_data` instead.
|
90
88
|
# @param level [String] The level. One of: 'critical', 'error', 'warning', 'info', 'debug'
|
91
|
-
# @param extra_data [Hash] Additional data to include alongside the body. Don't use 'body' as
|
89
|
+
# @param extra_data [Hash] Additional data to include alongside the body. Don't use 'body' as
|
92
90
|
# it is reserved.
|
93
91
|
def report_message(message, level = 'info', extra_data = {})
|
94
92
|
unless configuration.enabled
|
95
93
|
return
|
96
94
|
end
|
97
|
-
|
95
|
+
|
98
96
|
data = message_data(message, level, extra_data)
|
99
97
|
payload = build_payload(data)
|
100
98
|
schedule_payload(payload)
|
@@ -102,6 +100,21 @@ module Ratchetio
|
|
102
100
|
logger.error "[Ratchet.io] Error reporting message to Ratchet.io: #{e}"
|
103
101
|
end
|
104
102
|
|
103
|
+
# Turns off reporting for the given block.
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# Ratchetio.silenced { raise }
|
107
|
+
#
|
108
|
+
# @yield Block which exceptions won't be reported.
|
109
|
+
def silenced
|
110
|
+
begin
|
111
|
+
yield
|
112
|
+
rescue => e
|
113
|
+
e.instance_variable_set(:@_ratchet_do_not_report, true)
|
114
|
+
raise
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
105
118
|
def process_payload(payload)
|
106
119
|
begin
|
107
120
|
if configuration.write_to_file
|
@@ -116,9 +129,25 @@ module Ratchetio
|
|
116
129
|
|
117
130
|
private
|
118
131
|
|
132
|
+
def ignored?(exception)
|
133
|
+
if filtered_level(exception) == 'ignore'
|
134
|
+
return true
|
135
|
+
end
|
136
|
+
|
137
|
+
if exception.instance_variable_get(:@_ratchet_do_not_report)
|
138
|
+
return true
|
139
|
+
end
|
140
|
+
|
141
|
+
false
|
142
|
+
end
|
143
|
+
|
144
|
+
def filtered_level(exception)
|
145
|
+
configuration.exception_level_filters[exception.class.name]
|
146
|
+
end
|
147
|
+
|
119
148
|
def message_data(message, level, extra_data)
|
120
149
|
data = base_data(level)
|
121
|
-
|
150
|
+
|
122
151
|
data[:body] = {
|
123
152
|
:message => {
|
124
153
|
:body => message.to_s
|
@@ -126,13 +155,13 @@ module Ratchetio
|
|
126
155
|
}
|
127
156
|
data[:body][:message].merge!(extra_data)
|
128
157
|
data[:server] = server_data
|
129
|
-
|
158
|
+
|
130
159
|
data
|
131
160
|
end
|
132
161
|
|
133
162
|
def exception_data(exception, force_level = nil)
|
134
163
|
data = base_data
|
135
|
-
|
164
|
+
|
136
165
|
data[:level] = force_level if force_level
|
137
166
|
|
138
167
|
# parse backtrace
|
@@ -159,7 +188,7 @@ module Ratchetio
|
|
159
188
|
}
|
160
189
|
|
161
190
|
data[:server] = server_data
|
162
|
-
|
191
|
+
|
163
192
|
data
|
164
193
|
end
|
165
194
|
|
@@ -170,7 +199,7 @@ module Ratchetio
|
|
170
199
|
end
|
171
200
|
configuration.logger
|
172
201
|
end
|
173
|
-
|
202
|
+
|
174
203
|
def write_payload(payload)
|
175
204
|
if configuration.use_async
|
176
205
|
@file_semaphore.synchronize {
|
@@ -180,15 +209,15 @@ module Ratchetio
|
|
180
209
|
do_write_payload(payload)
|
181
210
|
end
|
182
211
|
end
|
183
|
-
|
212
|
+
|
184
213
|
def do_write_payload(payload)
|
185
214
|
logger.info '[Ratchet.io] Writing payload to file'
|
186
|
-
|
215
|
+
|
187
216
|
begin
|
188
217
|
unless @file
|
189
218
|
@file = File.open(configuration.filepath, "a")
|
190
219
|
end
|
191
|
-
|
220
|
+
|
192
221
|
@file.puts payload
|
193
222
|
@file.flush
|
194
223
|
logger.info "[Ratchet.io] Success"
|
@@ -196,13 +225,13 @@ module Ratchetio
|
|
196
225
|
logger.error "[Ratchet.io] Error opening/writing to file: #{e}"
|
197
226
|
end
|
198
227
|
end
|
199
|
-
|
228
|
+
|
200
229
|
def send_payload(payload)
|
201
230
|
logger.info '[Ratchet.io] Sending payload'
|
202
|
-
|
231
|
+
|
203
232
|
uri = URI.parse(configuration.endpoint)
|
204
233
|
http = Net::HTTP.new(uri.host, uri.port)
|
205
|
-
|
234
|
+
|
206
235
|
if uri.scheme == 'https'
|
207
236
|
http.use_ssl = true
|
208
237
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -219,21 +248,21 @@ module Ratchetio
|
|
219
248
|
logger.info "[Ratchet.io] Response: #{response.body}"
|
220
249
|
end
|
221
250
|
end
|
222
|
-
|
251
|
+
|
223
252
|
def schedule_payload(payload)
|
224
253
|
logger.info '[Ratchet.io] Scheduling payload'
|
225
|
-
|
254
|
+
|
226
255
|
if configuration.use_async
|
227
256
|
unless configuration.async_handler
|
228
257
|
configuration.async_handler = method(:default_async_handler)
|
229
258
|
end
|
230
|
-
|
259
|
+
|
231
260
|
if configuration.write_to_file
|
232
261
|
unless @file_semaphore
|
233
262
|
@file_semaphore = Mutex.new
|
234
263
|
end
|
235
264
|
end
|
236
|
-
|
265
|
+
|
237
266
|
configuration.async_handler.call(payload)
|
238
267
|
else
|
239
268
|
process_payload(payload)
|
@@ -261,26 +290,26 @@ module Ratchetio
|
|
261
290
|
:version => VERSION
|
262
291
|
}
|
263
292
|
}
|
264
|
-
|
293
|
+
|
265
294
|
if defined?(SecureRandom) and SecureRandom.respond_to?(:uuid)
|
266
295
|
data[:uuid] = SecureRandom.uuid
|
267
296
|
end
|
268
|
-
|
297
|
+
|
269
298
|
data
|
270
299
|
end
|
271
300
|
|
272
301
|
def server_data
|
273
302
|
config = configuration
|
274
|
-
|
303
|
+
|
275
304
|
data = {
|
276
305
|
:host => Socket.gethostname
|
277
306
|
}
|
278
307
|
data[:root] = config.root.to_s if config.root
|
279
308
|
data[:branch] = config.branch if config.branch
|
280
|
-
|
309
|
+
|
281
310
|
data
|
282
311
|
end
|
283
|
-
|
312
|
+
|
284
313
|
def default_async_handler(payload)
|
285
314
|
if defined?(GirlFriday)
|
286
315
|
unless @queue
|
@@ -288,7 +317,7 @@ module Ratchetio
|
|
288
317
|
process_payload(payload)
|
289
318
|
end
|
290
319
|
end
|
291
|
-
|
320
|
+
|
292
321
|
@queue.push(payload)
|
293
322
|
else
|
294
323
|
logger.warn '[Ratchet.io] girl_friday not found to handle async call, falling back to Thread'
|
@@ -3,7 +3,7 @@ class HomeController < ApplicationController
|
|
3
3
|
@users = User.all
|
4
4
|
|
5
5
|
Ratchetio.report_message("Test message from controller with no data", "debug")
|
6
|
-
Ratchetio.report_message("Test message from controller with extra data", "debug",
|
6
|
+
Ratchetio.report_message("Test message from controller with extra data", "debug",
|
7
7
|
:foo => "bar", :num_users => @users.length)
|
8
8
|
end
|
9
9
|
|
data/spec/ratchetio_spec.rb
CHANGED
@@ -10,14 +10,14 @@ describe Ratchetio do
|
|
10
10
|
Ratchetio.configure do |config|
|
11
11
|
config.logger = logger_mock
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
begin
|
15
15
|
foo = bar
|
16
16
|
rescue => e
|
17
17
|
@exception = e
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
let(:logger_mock) { double("Rails.logger").as_null_object }
|
22
22
|
|
23
23
|
it 'should report exceptions without person or request data' do
|
@@ -30,9 +30,9 @@ describe Ratchetio do
|
|
30
30
|
Ratchetio.configure do |config|
|
31
31
|
config.enabled = false
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
Ratchetio.report_exception(@exception)
|
35
|
-
|
35
|
+
|
36
36
|
Ratchetio.configure do |config|
|
37
37
|
config.enabled = true
|
38
38
|
end
|
@@ -66,14 +66,30 @@ describe Ratchetio do
|
|
66
66
|
logger_mock.should_not_receive(:info)
|
67
67
|
logger_mock.should_not_receive(:warn)
|
68
68
|
logger_mock.should_not_receive(:error)
|
69
|
-
|
69
|
+
|
70
70
|
Ratchetio.report_exception(@exception)
|
71
|
-
|
71
|
+
|
72
72
|
Ratchetio.configure do |config|
|
73
73
|
config.exception_level_filters = saved_filters
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
it 'should not report exceptions when silenced' do
|
78
|
+
Ratchetio.should_not_receive :schedule_payload
|
79
|
+
|
80
|
+
begin
|
81
|
+
test_var = 1
|
82
|
+
Ratchetio.silenced do
|
83
|
+
test_var = 2
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
rescue => e
|
87
|
+
Ratchetio.report_exception(e)
|
88
|
+
end
|
89
|
+
|
90
|
+
test_var.should == 2
|
91
|
+
end
|
92
|
+
|
77
93
|
it 'should report exception objects with no backtrace' do
|
78
94
|
payload = nil
|
79
95
|
Ratchetio.stub(:schedule_payload) do |*args|
|
@@ -93,7 +109,7 @@ describe Ratchetio do
|
|
93
109
|
end
|
94
110
|
end
|
95
111
|
end
|
96
|
-
|
112
|
+
|
97
113
|
context 'report_message' do
|
98
114
|
before(:each) do
|
99
115
|
configure
|
@@ -101,7 +117,7 @@ describe Ratchetio do
|
|
101
117
|
config.logger = logger_mock
|
102
118
|
end
|
103
119
|
end
|
104
|
-
|
120
|
+
|
105
121
|
let(:logger_mock) { double("Rails.logger").as_null_object }
|
106
122
|
|
107
123
|
it 'should report simple messages' do
|
@@ -115,9 +131,9 @@ describe Ratchetio do
|
|
115
131
|
Ratchetio.configure do |config|
|
116
132
|
config.enabled = false
|
117
133
|
end
|
118
|
-
|
134
|
+
|
119
135
|
Ratchetio.report_message("Test message that should be ignored")
|
120
|
-
|
136
|
+
|
121
137
|
Ratchetio.configure do |config|
|
122
138
|
config.enabled = true
|
123
139
|
end
|
@@ -145,7 +161,7 @@ describe Ratchetio do
|
|
145
161
|
end
|
146
162
|
end
|
147
163
|
end
|
148
|
-
|
164
|
+
|
149
165
|
context 'payload_destination' do
|
150
166
|
before(:each) do
|
151
167
|
configure
|
@@ -153,83 +169,84 @@ describe Ratchetio do
|
|
153
169
|
config.logger = logger_mock
|
154
170
|
config.filepath = 'test.ratchet'
|
155
171
|
end
|
156
|
-
|
172
|
+
|
157
173
|
begin
|
158
174
|
foo = bar
|
159
175
|
rescue => e
|
160
176
|
@exception = e
|
161
177
|
end
|
162
178
|
end
|
163
|
-
|
179
|
+
|
164
180
|
let(:logger_mock) { double("Rails.logger").as_null_object }
|
165
|
-
|
181
|
+
|
166
182
|
it 'should send the payload over the network by default' do
|
167
183
|
logger_mock.should_not_receive(:info).with('[Ratchet.io] Writing payload to file')
|
168
184
|
logger_mock.should_receive(:info).with('[Ratchet.io] Sending payload')
|
169
185
|
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
170
186
|
Ratchetio.report_exception(@exception)
|
171
187
|
end
|
172
|
-
|
188
|
+
|
173
189
|
it 'should save the payload to a file if set' do
|
174
190
|
logger_mock.should_not_receive(:info).with('[Ratchet.io] Sending payload')
|
175
191
|
logger_mock.should_receive(:info).with('[Ratchet.io] Writing payload to file')
|
176
192
|
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
177
|
-
|
193
|
+
|
178
194
|
filepath = ''
|
179
|
-
|
195
|
+
|
180
196
|
Ratchetio.configure do |config|
|
181
197
|
config.write_to_file = true
|
182
198
|
filepath = config.filepath
|
183
199
|
end
|
184
|
-
|
200
|
+
|
185
201
|
Ratchetio.report_exception(@exception)
|
186
|
-
|
202
|
+
|
187
203
|
File.exist?(filepath).should == true
|
188
204
|
File.read(filepath).should include test_access_token
|
189
205
|
File.delete(filepath)
|
190
|
-
|
206
|
+
|
191
207
|
Ratchetio.configure do |config|
|
192
208
|
config.write_to_file = false
|
193
209
|
end
|
194
210
|
end
|
195
211
|
end
|
196
|
-
|
212
|
+
|
197
213
|
context 'asynchronous_handling' do
|
198
214
|
before(:each) do
|
199
215
|
configure
|
200
216
|
Ratchetio.configure do |config|
|
201
217
|
config.logger = logger_mock
|
202
218
|
end
|
203
|
-
|
219
|
+
|
204
220
|
begin
|
205
221
|
foo = bar
|
206
222
|
rescue => e
|
207
223
|
@exception = e
|
208
224
|
end
|
209
225
|
end
|
210
|
-
|
226
|
+
|
211
227
|
let(:logger_mock) { double("Rails.logger").as_null_object }
|
212
|
-
|
228
|
+
|
213
229
|
it 'should send the payload using the default asynchronous handler girl_friday' do
|
214
230
|
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
215
|
-
|
231
|
+
|
216
232
|
Ratchetio.configure do |config|
|
217
233
|
config.use_async = true
|
218
234
|
GirlFriday::WorkQueue::immediate!
|
219
235
|
end
|
220
|
-
|
236
|
+
|
221
237
|
Ratchetio.report_exception(@exception)
|
222
|
-
|
238
|
+
|
223
239
|
Ratchetio.configure do |config|
|
224
240
|
config.use_async = false
|
225
241
|
GirlFriday::WorkQueue::queue!
|
226
242
|
end
|
227
243
|
end
|
228
|
-
|
244
|
+
|
229
245
|
it 'should send the payload using a user-supplied asynchronous handler' do
|
230
246
|
logger_mock.should_receive(:info).with('Custom async handler called')
|
247
|
+
logger_mock.should_receive(:info).with('[Ratchet.io] Sending payload')
|
231
248
|
logger_mock.should_receive(:info).with('[Ratchet.io] Success')
|
232
|
-
|
249
|
+
|
233
250
|
Ratchetio.configure do |config|
|
234
251
|
config.use_async = true
|
235
252
|
config.async_handler = Proc.new { |payload|
|
@@ -237,9 +254,9 @@ describe Ratchetio do
|
|
237
254
|
Ratchetio.process_payload(payload)
|
238
255
|
}
|
239
256
|
end
|
240
|
-
|
257
|
+
|
241
258
|
Ratchetio.report_exception(@exception)
|
242
|
-
|
259
|
+
|
243
260
|
Ratchetio.configure do |config|
|
244
261
|
config.use_async = false
|
245
262
|
config.async_handler = Ratchetio.method(:default_async_handler)
|
@@ -264,16 +281,16 @@ describe Ratchetio do
|
|
264
281
|
user_id = 123
|
265
282
|
name = "Tester"
|
266
283
|
|
267
|
-
data = Ratchetio.send(:message_data, @message_body, 'info',
|
284
|
+
data = Ratchetio.send(:message_data, @message_body, 'info',
|
268
285
|
:user_id => user_id, :name => name)
|
269
|
-
|
286
|
+
|
270
287
|
message = data[:body][:message]
|
271
288
|
message[:body].should == @message_body
|
272
289
|
message[:user_id].should == user_id
|
273
290
|
message[:name].should == name
|
274
291
|
end
|
275
292
|
end
|
276
|
-
|
293
|
+
|
277
294
|
context 'exception_data' do
|
278
295
|
before(:each) do
|
279
296
|
configure
|
@@ -283,7 +300,7 @@ describe Ratchetio do
|
|
283
300
|
@exception = e
|
284
301
|
end
|
285
302
|
end
|
286
|
-
|
303
|
+
|
287
304
|
it 'should accept force_level' do
|
288
305
|
level = 'critical'
|
289
306
|
data = Ratchetio.send(:exception_data, @exception, level)
|
@@ -292,11 +309,11 @@ describe Ratchetio do
|
|
292
309
|
|
293
310
|
it 'should build valid exception data' do
|
294
311
|
data = Ratchetio.send(:exception_data, @exception)
|
295
|
-
|
312
|
+
|
296
313
|
data[:level].should_not be_nil
|
297
|
-
|
314
|
+
|
298
315
|
trace = data[:body][:trace]
|
299
|
-
|
316
|
+
|
300
317
|
frames = trace[:frames]
|
301
318
|
frames.should be_a_kind_of(Array)
|
302
319
|
frames.each do |frame|
|
@@ -306,14 +323,14 @@ describe Ratchetio do
|
|
306
323
|
frame[:method].should be_a_kind_of(String)
|
307
324
|
end
|
308
325
|
end
|
309
|
-
|
326
|
+
|
310
327
|
# should be NameError, but can be NoMethodError sometimes on rubinius 1.8
|
311
328
|
# http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
|
312
329
|
trace[:exception][:class].should match(/^(NameError|NoMethodError)$/)
|
313
330
|
trace[:exception][:message].should match(/^(undefined local variable or method `bar'|undefined method `bar' on an instance of)/)
|
314
331
|
end
|
315
332
|
end
|
316
|
-
|
333
|
+
|
317
334
|
context 'logger' do
|
318
335
|
before(:each) do
|
319
336
|
reset_configuration
|
@@ -340,7 +357,7 @@ describe Ratchetio do
|
|
340
357
|
reset_configuration
|
341
358
|
end
|
342
359
|
end
|
343
|
-
|
360
|
+
|
344
361
|
context 'build_payload' do
|
345
362
|
it 'should build valid json' do
|
346
363
|
json = Ratchetio.send(:build_payload, {:foo => {:bar => "baz"}})
|
@@ -357,7 +374,7 @@ describe Ratchetio do
|
|
357
374
|
it 'should have the correct notifier name' do
|
358
375
|
Ratchetio.send(:base_data)[:notifier][:name].should == 'ratchetio-gem'
|
359
376
|
end
|
360
|
-
|
377
|
+
|
361
378
|
it 'should have the correct notifier version' do
|
362
379
|
Ratchetio.send(:base_data)[:notifier][:version].should == Ratchetio::VERSION
|
363
380
|
end
|