metybur 0.3.0 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f69ccd216fe6e46fe9472a0975e31de3c15a9c14
4
- data.tar.gz: 91fdac926fc0e44432c67da5e27a072e7e027ab8
3
+ metadata.gz: 864d272f4639c0789e198773313fcad042332ad5
4
+ data.tar.gz: d840163bb51fd06be5af41af567a638d8528ee53
5
5
  SHA512:
6
- metadata.gz: 020974269a114c7ed5edba2b2d8a7168931d7dd61ea81064a8a1df0a18464a564b703eb9fcae536e8d3ec1526ee2affab60cab47e1f1b7443e11cc41cdb127b2
7
- data.tar.gz: 9682e9bcd748d3aa069fab63548672a522dda50eae8dafe4beadea581641b95b095a7f35e6bae4720b176d2bea1357594eec7a818fd8ce68338d692d857d1122
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 days 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
+ > 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
  >
@@ -9,8 +9,7 @@ class Metybur::Collection
9
9
  end
10
10
 
11
11
  def on(event, &block)
12
- @callbacks[event] ||= []
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
- @callbacks[event].each { |callback| callback.call(*arguments) }
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,13 @@
1
+ class Metybur::JSONMiddleware
2
+ def open(event)
3
+ event
4
+ end
5
+
6
+ def message(event)
7
+ JSON.parse(event.data, symbolize_names: true)
8
+ end
9
+
10
+ def close(event)
11
+ event
12
+ end
13
+ 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
@@ -1,3 +1,3 @@
1
1
  module Metybur
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
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
- logger = Logger.new(CONFIG[:log_stream])
19
- logger.level = CONFIG[:log_level]
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
- logger.debug 'connection open'
27
+ middleware.inject(event) { |e, mw| mw.open(e) }
22
28
  end
23
- websocket.on(:message) do |message|
24
- logger.debug "received message #{message.data}"
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
- logger.debug "connection closed (code #{event.code}). #{event.reason}"
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
- it 'responds with pong to a ping' do
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
- it 'gets notified when a record is added' do
154
- collection = FFaker::Internet.user_name
155
- id = FFaker::Guid.guid
156
- fields = {city: FFaker::Address.city}
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 = Metybur.connect(url)
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.0
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-05-12 00:00:00.000000000 Z
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.2.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.