metybur 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/metybur/collection.rb +6 -3
- data/lib/metybur/middleware/json_middleware.rb +13 -0
- data/lib/metybur/middleware/logging_middleware.rb +21 -0
- data/lib/metybur/middleware/ping_pong_middleware.rb +22 -0
- data/lib/metybur/version.rb +1 -1
- data/lib/metybur.rb +12 -15
- data/spec/metybur_spec.rb +25 -46
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 864d272f4639c0789e198773313fcad042332ad5
|
4
|
+
data.tar.gz: d840163bb51fd06be5af41af567a638d8528ee53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e39ffccc52cdc71c27e4f27750b86352f96f24251ca7eb49a966f00956d41b3a0ecdfc3f558073b63f53f8a0ca879e989f6de6ff700b9680fecc002b80b2385
|
7
|
+
data.tar.gz: 441ecdfcbd89231ccea2b0c608b2a354c73c15bbb1ef2beadcf949844bfdb0cafd1f1678c5290b9f29dd600c4fa08ff953a32b6469f7e274443562c09b279c08
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Metybur
|
2
2
|
[![Build Status](https://travis-ci.org/clemenshelm/metybur.svg?branch=master)](https://travis-ci.org/clemenshelm/metybur)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/metybur.svg)](http://badge.fury.io/rb/metybur)
|
3
4
|
|
4
5
|
A DDP client for Ruby to connect to Meteor apps.
|
5
6
|
|
@@ -9,7 +10,7 @@ You can also call Meteor methods from Ruby.
|
|
9
10
|
|
10
11
|
> ## Caution!
|
11
12
|
>
|
12
|
-
> This gem is just a few
|
13
|
+
> This gem is just a few weeks old so far and doesn't include basic features like proper error handling. Also only a subset of the DDP protocol is implemented so far. Everything described in this README should work, though.
|
13
14
|
>
|
14
15
|
> I'll keep working on it constantly, so I suppose there will be a complete and stable version soon. Stay tuned!
|
15
16
|
>
|
data/lib/metybur/collection.rb
CHANGED
@@ -9,8 +9,7 @@ class Metybur::Collection
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def on(event, &block)
|
12
|
-
|
13
|
-
@callbacks[event] << block
|
12
|
+
callback_for(event: event) << block
|
14
13
|
self
|
15
14
|
end
|
16
15
|
|
@@ -19,6 +18,10 @@ class Metybur::Collection
|
|
19
18
|
def handle_message(attributes)
|
20
19
|
event = attributes[:msg].to_sym
|
21
20
|
arguments = attributes.slice(:id, :fields, :cleared).values
|
22
|
-
|
21
|
+
callback_for(event: event).each { |callback| callback.call(*arguments) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def callback_for(event:)
|
25
|
+
@callbacks[event] ||= []
|
23
26
|
end
|
24
27
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Metybur::LoggingMiddleware
|
2
|
+
def initialize
|
3
|
+
@logger = Logger.new(Metybur::CONFIG[:log_stream])
|
4
|
+
@logger.level = Metybur::CONFIG[:log_level]
|
5
|
+
end
|
6
|
+
|
7
|
+
def open(event)
|
8
|
+
@logger.debug 'connection open'
|
9
|
+
event
|
10
|
+
end
|
11
|
+
|
12
|
+
def message(event)
|
13
|
+
@logger.debug "received message #{event.data}"
|
14
|
+
event
|
15
|
+
end
|
16
|
+
|
17
|
+
def close(event)
|
18
|
+
@logger.debug "connection closed (code #{event.code}). #{event.reason}"
|
19
|
+
event
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Metybur::PingPongMiddleware
|
2
|
+
def initialize(websocket)
|
3
|
+
# TODO: This dependency is dowdy. Get rid of it.
|
4
|
+
@websocket = websocket
|
5
|
+
end
|
6
|
+
|
7
|
+
def open(event)
|
8
|
+
event
|
9
|
+
end
|
10
|
+
|
11
|
+
def message(message)
|
12
|
+
return message unless message[:msg] == 'ping'
|
13
|
+
pong = {msg: 'pong'}
|
14
|
+
pong[:id] = message[:id] if message[:id]
|
15
|
+
@websocket.send(pong.to_json)
|
16
|
+
message
|
17
|
+
end
|
18
|
+
|
19
|
+
def close(event)
|
20
|
+
event
|
21
|
+
end
|
22
|
+
end
|
data/lib/metybur/version.rb
CHANGED
data/lib/metybur.rb
CHANGED
@@ -3,6 +3,9 @@ require 'faye/websocket'
|
|
3
3
|
require 'json'
|
4
4
|
require 'logger'
|
5
5
|
require_relative 'metybur/client'
|
6
|
+
require_relative 'metybur/middleware/logging_middleware'
|
7
|
+
require_relative 'metybur/middleware/json_middleware'
|
8
|
+
require_relative 'metybur/middleware/ping_pong_middleware'
|
6
9
|
|
7
10
|
module Metybur
|
8
11
|
CONFIG = {
|
@@ -15,28 +18,22 @@ module Metybur
|
|
15
18
|
websocket = CONFIG[:websocket_client_class].new(url)
|
16
19
|
client = Metybur::Client.new(websocket)
|
17
20
|
|
18
|
-
|
19
|
-
|
21
|
+
logging_middleware = Metybur::LoggingMiddleware.new
|
22
|
+
json_middleware = Metybur::JSONMiddleware.new
|
23
|
+
ping_pong_middleware = Metybur::PingPongMiddleware.new(websocket)
|
24
|
+
middleware = [logging_middleware, json_middleware, ping_pong_middleware]
|
25
|
+
|
20
26
|
websocket.on(:open) do |event|
|
21
|
-
|
27
|
+
middleware.inject(event) { |e, mw| mw.open(e) }
|
22
28
|
end
|
23
|
-
websocket.on(:message) do |
|
24
|
-
|
29
|
+
websocket.on(:message) do |event|
|
30
|
+
middleware.inject(event) { |e, mw| mw.message(e) }
|
25
31
|
end
|
26
32
|
websocket.on(:close) do |event|
|
27
|
-
|
33
|
+
middleware.inject(event) { |e, mw| mw.close(e) }
|
28
34
|
EM.stop_event_loop
|
29
35
|
end
|
30
36
|
|
31
|
-
websocket.on(:message) do |event|
|
32
|
-
message = JSON.parse(event.data, symbolize_names: true)
|
33
|
-
if message[:msg] == 'ping'
|
34
|
-
pong = {msg: 'pong'}
|
35
|
-
pong[:id] = message[:id] if message[:id]
|
36
|
-
websocket.send(pong.to_json)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
37
|
connect_message = {
|
41
38
|
msg: 'connect',
|
42
39
|
version: '1',
|
data/spec/metybur_spec.rb
CHANGED
@@ -86,17 +86,17 @@ describe Metybur do
|
|
86
86
|
end
|
87
87
|
|
88
88
|
context 'ping pong' do
|
89
|
-
|
89
|
+
before :each do
|
90
90
|
Metybur.connect(url)
|
91
|
+
end
|
91
92
|
|
93
|
+
it 'responds with pong to a ping' do
|
92
94
|
websocket.receive({msg: 'ping'}.to_json)
|
93
|
-
|
94
95
|
expect(last_sent_message[:msg]).to eq 'pong'
|
95
96
|
end
|
96
97
|
|
97
98
|
it 'includes the same id in the pong message' do
|
98
99
|
id = FFaker::Guid.guid
|
99
|
-
Metybur.connect(url)
|
100
100
|
|
101
101
|
websocket.receive({msg: 'ping', id: id}.to_json)
|
102
102
|
|
@@ -105,17 +105,15 @@ describe Metybur do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
it "doesn't include an id if the ping message contained none" do
|
108
|
-
Metybur.connect(url)
|
109
|
-
|
110
108
|
websocket.receive({msg: 'ping'}.to_json)
|
111
|
-
|
112
109
|
expect(last_sent_message).not_to have_key :id
|
113
110
|
end
|
114
111
|
end
|
115
112
|
|
116
113
|
context 'logging' do
|
114
|
+
let(:output) { StringIO.new }
|
115
|
+
|
117
116
|
it "doesn't log any messages by default" do
|
118
|
-
output = StringIO.new
|
119
117
|
Metybur.log_stream = output
|
120
118
|
Metybur.connect(url)
|
121
119
|
|
@@ -125,7 +123,6 @@ describe Metybur do
|
|
125
123
|
end
|
126
124
|
|
127
125
|
it 'logs a message when the log level is set to debug' do
|
128
|
-
output = StringIO.new
|
129
126
|
Metybur.log_level = :debug
|
130
127
|
Metybur.log_stream = output
|
131
128
|
Metybur.connect(url)
|
@@ -150,13 +147,12 @@ describe Metybur do
|
|
150
147
|
end
|
151
148
|
|
152
149
|
context 'collections' do
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
meteor = Metybur.connect(url)
|
150
|
+
let(:collection) { FFaker::Lorem.word }
|
151
|
+
let(:id) { FFaker::Guid.guid }
|
152
|
+
let!(:meteor) { Metybur.connect(url) }
|
153
|
+
let(:fields) { {city: FFaker::Address.city} }
|
159
154
|
|
155
|
+
it 'gets notified when a record is added' do
|
160
156
|
wait_for_callback do |done|
|
161
157
|
meteor.collection(collection)
|
162
158
|
.on(:added) do |added_id, added_fields|
|
@@ -176,13 +172,8 @@ describe Metybur do
|
|
176
172
|
end
|
177
173
|
|
178
174
|
it 'gets notified when a record is changed' do
|
179
|
-
collection = FFaker::Internet.user_name
|
180
|
-
id = FFaker::Guid.guid
|
181
|
-
fields = {city: FFaker::Address.city}
|
182
175
|
cleared = [FFaker::Guid.guid]
|
183
176
|
|
184
|
-
meteor = Metybur.connect(url)
|
185
|
-
|
186
177
|
wait_for_callback do |done|
|
187
178
|
meteor.collection(collection)
|
188
179
|
.on(:changed) do |changed_id, changed_fields, cleared_fields|
|
@@ -204,11 +195,6 @@ describe Metybur do
|
|
204
195
|
end
|
205
196
|
|
206
197
|
it 'gets notified when a record is removed' do
|
207
|
-
collection = FFaker::Internet.user_name
|
208
|
-
id = FFaker::Guid.guid
|
209
|
-
|
210
|
-
meteor = Metybur.connect(url)
|
211
|
-
|
212
198
|
wait_for_callback do |done|
|
213
199
|
meteor.collection(collection)
|
214
200
|
.on(:removed) do |removed_id|
|
@@ -226,7 +212,6 @@ describe Metybur do
|
|
226
212
|
end
|
227
213
|
|
228
214
|
it 'lets the `on` method be chainable' do
|
229
|
-
meteor = Metybur.connect(url)
|
230
215
|
meteor.collection('my-collection')
|
231
216
|
.on(:added) { anything }
|
232
217
|
.on(:changed) { anything }
|
@@ -236,12 +221,6 @@ describe Metybur do
|
|
236
221
|
end
|
237
222
|
|
238
223
|
it 'registers multiple added callbacks' do
|
239
|
-
collection = FFaker::Internet.user_name
|
240
|
-
id = FFaker::Guid.guid
|
241
|
-
fields = {city: FFaker::Address.city}
|
242
|
-
|
243
|
-
meteor = Metybur.connect(url)
|
244
|
-
|
245
224
|
wait_for_callback(calls: 2) do |done|
|
246
225
|
meteor.collection(collection)
|
247
226
|
.on(:added) { |added_id, added_fields| done.call() }
|
@@ -257,8 +236,19 @@ describe Metybur do
|
|
257
236
|
end
|
258
237
|
end
|
259
238
|
|
239
|
+
it 'does nothing if there is no callback for an event' do
|
240
|
+
meteor.collection(collection)
|
241
|
+
|
242
|
+
message = {
|
243
|
+
msg: 'added',
|
244
|
+
collection: collection,
|
245
|
+
id: id,
|
246
|
+
fields: fields
|
247
|
+
}.to_json
|
248
|
+
websocket.receive message
|
249
|
+
end
|
250
|
+
|
260
251
|
it "doesn't get notified of a ping message" do
|
261
|
-
meteor = Metybur.connect(url)
|
262
252
|
meteor.collection('my-collection')
|
263
253
|
.on(:added) { fail('Callback got called') }
|
264
254
|
|
@@ -266,7 +256,6 @@ describe Metybur do
|
|
266
256
|
end
|
267
257
|
|
268
258
|
it "doesn't get notified of a record from another collection" do
|
269
|
-
meteor = Metybur.connect(url)
|
270
259
|
meteor.collection('my-collection')
|
271
260
|
.on(:added) { fail('Callback got called') }
|
272
261
|
|
@@ -281,6 +270,8 @@ describe Metybur do
|
|
281
270
|
end
|
282
271
|
|
283
272
|
context 'methods' do
|
273
|
+
let!(:meteor) { Metybur.connect(url) }
|
274
|
+
|
284
275
|
it 'calls a method through the call method' do
|
285
276
|
method = %w(postChatMessage sendEmail submitOrder).sample
|
286
277
|
params = %w(35 Vienna true).sample(2)
|
@@ -288,7 +279,6 @@ describe Metybur do
|
|
288
279
|
.to_a.sample(2)
|
289
280
|
params << Hash[hashParams]
|
290
281
|
|
291
|
-
meteor = Metybur.connect(url)
|
292
282
|
meteor.call(method, params)
|
293
283
|
|
294
284
|
expect(last_sent_message[:msg]).to eq 'method'
|
@@ -298,7 +288,6 @@ describe Metybur do
|
|
298
288
|
end
|
299
289
|
|
300
290
|
it 'calls a method called on the client directly' do
|
301
|
-
meteor = Metybur.connect(url)
|
302
291
|
meteor.activate('user', id: 'utrtrvlc')
|
303
292
|
|
304
293
|
expect(last_sent_message[:msg]).to eq 'method'
|
@@ -308,7 +297,6 @@ describe Metybur do
|
|
308
297
|
end
|
309
298
|
|
310
299
|
it 'camel-cases methods and parameters called on the client directly' do
|
311
|
-
meteor = Metybur.connect(url)
|
312
300
|
meteor.activate_user('Hans', user_id: 'utrtrvlc', is_admin: false)
|
313
301
|
|
314
302
|
expect(last_sent_message[:msg]).to eq 'method'
|
@@ -318,7 +306,6 @@ describe Metybur do
|
|
318
306
|
end
|
319
307
|
|
320
308
|
it 'passes the result to a block' do
|
321
|
-
meteor = Metybur.connect(url)
|
322
309
|
expectation = proc { |result| expect(result[:price]).to eq 99 }
|
323
310
|
|
324
311
|
wait_for_callback do |done|
|
@@ -337,17 +324,11 @@ describe Metybur do
|
|
337
324
|
end
|
338
325
|
|
339
326
|
it "doesn't trigger the callback for ping messages" do
|
340
|
-
meteor
|
341
|
-
|
342
|
-
meteor.get_product(27) do
|
343
|
-
fail
|
344
|
-
end
|
345
|
-
|
327
|
+
meteor.get_product(27) { fail }
|
346
328
|
websocket.receive({msg: 'ping'}.to_json)
|
347
329
|
end
|
348
330
|
|
349
331
|
it 'triggers the callback with the right result' do
|
350
|
-
meteor = Metybur.connect(url)
|
351
332
|
expectation = proc { |result| expect(result[:price]).to eq 99 }
|
352
333
|
|
353
334
|
wait_for_callback do |done|
|
@@ -371,7 +352,6 @@ describe Metybur do
|
|
371
352
|
end
|
372
353
|
|
373
354
|
it 'raises an error if an exception occurs in the method' do
|
374
|
-
meteor = Metybur.connect(url)
|
375
355
|
error = FFaker::Lorem.word
|
376
356
|
reason = FFaker::Lorem.sentence
|
377
357
|
details = FFaker::Lorem.paragraph
|
@@ -402,7 +382,6 @@ describe Metybur do
|
|
402
382
|
end
|
403
383
|
|
404
384
|
it 'raises an error if an exception occurs in the method' do
|
405
|
-
meteor = Metybur.connect(url)
|
406
385
|
error = FFaker::Lorem.word
|
407
386
|
reason = FFaker::Lorem.sentence
|
408
387
|
details = FFaker::Lorem.paragraph
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metybur
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clemens Helm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faye-websocket
|
@@ -129,6 +129,9 @@ files:
|
|
129
129
|
- lib/metybur/client.rb
|
130
130
|
- lib/metybur/collection.rb
|
131
131
|
- lib/metybur/method.rb
|
132
|
+
- lib/metybur/middleware/json_middleware.rb
|
133
|
+
- lib/metybur/middleware/logging_middleware.rb
|
134
|
+
- lib/metybur/middleware/ping_pong_middleware.rb
|
132
135
|
- lib/metybur/version.rb
|
133
136
|
- metybur.gemspec
|
134
137
|
- spec/metybur_spec.rb
|
@@ -154,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
157
|
version: '0'
|
155
158
|
requirements: []
|
156
159
|
rubyforge_project:
|
157
|
-
rubygems_version: 2.
|
160
|
+
rubygems_version: 2.4.5
|
158
161
|
signing_key:
|
159
162
|
specification_version: 4
|
160
163
|
summary: DDP client for Ruby to connect to Meteor apps.
|