metybur 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f8193384592b340b1a3f5fe89ca5c17df23dbabe
4
- data.tar.gz: 7ef7c3b8a4eeb9f66ce756a7f7b3dc19e4293f3b
3
+ metadata.gz: 6cd1e4839ca1350e3e953be00f1428c1fbf31b84
4
+ data.tar.gz: e344a1a7e9537edd9eeb1f925518880b9f431e17
5
5
  SHA512:
6
- metadata.gz: 053934c755a3801efb5f502991f73c50335ccd148525c761eef46f007527226c384f9604e69e0b37c181d2e44da7558dce0ae5b2f8a9e826ce7e5a22ac3114d0
7
- data.tar.gz: ac70963429fdf3b0136f409508246f5e18f9130fb821b4bbfde614082db19365f4011b11fcf3037944f7564b51625650a784ec09d1d0d2e15efbfa15ef4df8f8
6
+ metadata.gz: 863a4003723aade726d6a753a15dacb6d5666f7dd5b5453048ed8eb9557f48dfb940d530431d3cc38e358de4fcdd3fd73793bb4f1af8264e85919d12409e062e
7
+ data.tar.gz: dd9b0fa2281be1a3441d6069c408b1b896e665dd93f5c3c57114ed9ce9fd2756295361cf7afccba14d299e4a019772bfaccbe1c336951ca7f545f535d7c59ca4
data/README.md CHANGED
@@ -137,6 +137,24 @@ meteor.call('postChatMessage', inRoom: 'General')
137
137
 
138
138
  Note that you have to choose this syntax, if your Meteor method name collides with a Metybur method (like `collection` or `subscribe`).
139
139
 
140
+ #### Results
141
+
142
+ Since methods are executed asynchronously, they won't return a result immediately:
143
+
144
+ ```ruby
145
+ # Doesn't work!
146
+ messages = meteor.chat_messages(in_room: 'General')
147
+ messages.each { |message| puts message }
148
+ ```
149
+
150
+ Instead, pass a block to the method. The block will get called once the result arrives.
151
+
152
+ ```ruby
153
+ meteor.chat_messages(in_room: 'General') do |messages|
154
+ messages.each { |message| puts message }
155
+ end
156
+ ```
157
+
140
158
  ### Logging
141
159
 
142
160
  To debug your application, you can lower the log level to see all incoming websocket messages.
@@ -1,5 +1,6 @@
1
1
  require 'active_support/inflector'
2
2
  require_relative 'collection'
3
+ require_relative 'method'
3
4
 
4
5
  class Metybur::Client
5
6
  def initialize(websocket)
@@ -19,17 +20,15 @@ class Metybur::Client
19
20
  Metybur::Collection.new(name, @websocket)
20
21
  end
21
22
 
22
- def call(method, params)
23
- message = {
24
- msg: 'method',
25
- id: 'efg',
26
- method: method,
27
- params: params
28
- }.to_json
29
- @websocket.send message
23
+ def method(name)
24
+ Metybur::Method.new(name, @websocket)
25
+ end
26
+
27
+ def call(method_name, params, &block)
28
+ method(method_name).call(params, &block)
30
29
  end
31
30
 
32
- def method_missing(method, *params)
31
+ def method_missing(method, *params, &block)
33
32
  method = method.to_s.camelize(:lower)
34
33
  params.map! do |param|
35
34
  case param
@@ -40,6 +39,6 @@ class Metybur::Client
40
39
  param
41
40
  end
42
41
  end
43
- call(method, params)
42
+ call(method, params, &block)
44
43
  end
45
44
  end
@@ -0,0 +1,33 @@
1
+ class Metybur::Method
2
+ def initialize(name, websocket)
3
+ require 'securerandom'
4
+
5
+ @name = name
6
+ @websocket = websocket
7
+ @callbacks = {}
8
+
9
+ @websocket.on(:message) do |event|
10
+ attributes = JSON.parse(event.data, symbolize_names: true)
11
+ handle_message(attributes) if attributes[:msg] == 'result'
12
+ end
13
+ end
14
+
15
+ def call(params, &block)
16
+ id = SecureRandom.uuid
17
+ message = {
18
+ msg: 'method',
19
+ id: id,
20
+ method: @name,
21
+ params: params
22
+ }.to_json
23
+ @websocket.send message
24
+ @callbacks[id] = block
25
+ end
26
+
27
+ private
28
+
29
+ def handle_message(attributes)
30
+ id = attributes[:id]
31
+ @callbacks[id].call attributes[:result] if @callbacks[id]
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module Metybur
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/metybur.rb CHANGED
@@ -31,7 +31,9 @@ module Metybur
31
31
  websocket.on(:message) do |event|
32
32
  message = JSON.parse(event.data, symbolize_names: true)
33
33
  if message[:msg] == 'ping'
34
- websocket.send({msg: 'pong'}.to_json)
34
+ pong = {msg: 'pong'}
35
+ pong[:id] = message[:id] if message[:id]
36
+ websocket.send(pong.to_json)
35
37
  end
36
38
  end
37
39
 
data/spec/metybur_spec.rb CHANGED
@@ -16,8 +16,16 @@ describe Metybur do
16
16
  JSON.parse(string_data, symbolize_names: true)
17
17
  end
18
18
 
19
+ def wait_for_callback(options = {})
20
+ calls = options[:calls] || 1 # No keyword arguments in Ruby 1.9.3
21
+ times_called = 0
22
+ done = -> { times_called += 1 }
23
+ yield done
24
+ fail("Callback only got called #{times_called} time(s).") if times_called < calls
25
+ end
26
+
19
27
  it 'connects to a Meteor URL' do
20
- Metybur.connect url
28
+ Metybur.connect(url)
21
29
 
22
30
  expect(websocket.url).to eq url
23
31
  connect_message = parse(websocket.sent.first)
@@ -32,7 +40,7 @@ describe Metybur do
32
40
  email = FFaker::Internet.email
33
41
  password = FFaker::Internet.password
34
42
 
35
- Metybur.connect url, email: email, password: password
43
+ Metybur.connect(url, email: email, password: password)
36
44
 
37
45
  expect(last_sent_message[:msg]).to eq 'method'
38
46
  expect(last_sent_message).to have_key :id # we don't care about the value here
@@ -46,7 +54,7 @@ describe Metybur do
46
54
  username = FFaker::Internet.user_name
47
55
  password = FFaker::Internet.password
48
56
 
49
- Metybur.connect url, username: username, password: password
57
+ Metybur.connect(url, username: username, password: password)
50
58
 
51
59
  expect(last_sent_message[:msg]).to eq 'method'
52
60
  expect(last_sent_message).to have_key :id # we don't care about the value here
@@ -60,7 +68,7 @@ describe Metybur do
60
68
  userid = FFaker::Guid.guid
61
69
  password = FFaker::Internet.password
62
70
 
63
- Metybur.connect url, id: userid, password: password
71
+ Metybur.connect(url, id: userid, password: password)
64
72
 
65
73
  expect(last_sent_message[:msg]).to eq 'method'
66
74
  expect(last_sent_message).to have_key :id # we don't care about the value here
@@ -71,7 +79,7 @@ describe Metybur do
71
79
  end
72
80
 
73
81
  it "doesn't log in without credentials" do
74
- Metybur.connect url
82
+ Metybur.connect(url)
75
83
 
76
84
  expect(last_sent_message[:msg]).to eq 'connect'
77
85
  end
@@ -79,20 +87,37 @@ describe Metybur do
79
87
 
80
88
  context 'ping pong' do
81
89
  it 'responds with pong to a ping' do
82
- Metybur.connect url
90
+ Metybur.connect(url)
83
91
 
84
92
  websocket.receive({msg: 'ping'}.to_json)
85
93
 
86
94
  expect(last_sent_message[:msg]).to eq 'pong'
87
95
  end
88
- end
89
96
 
97
+ it 'includes the same id in the pong message' do
98
+ id = FFaker::Guid.guid
99
+ Metybur.connect(url)
100
+
101
+ websocket.receive({msg: 'ping', id: id}.to_json)
102
+
103
+ expect(last_sent_message[:msg]).to eq 'pong'
104
+ expect(last_sent_message[:id]).to eq id
105
+ end
106
+
107
+ it "doesn't include an id if the ping message contained none" do
108
+ Metybur.connect(url)
109
+
110
+ websocket.receive({msg: 'ping'}.to_json)
111
+
112
+ expect(last_sent_message).not_to have_key :id
113
+ end
114
+ end
90
115
 
91
116
  context 'logging' do
92
117
  it "doesn't log any messages by default" do
93
118
  output = StringIO.new
94
119
  Metybur.log_stream = output
95
- Metybur.connect url
120
+ Metybur.connect(url)
96
121
 
97
122
  websocket.receive({msg: 'logged_message'}.to_json)
98
123
 
@@ -103,7 +128,7 @@ describe Metybur do
103
128
  output = StringIO.new
104
129
  Metybur.log_level = :debug
105
130
  Metybur.log_stream = output
106
- Metybur.connect url
131
+ Metybur.connect(url)
107
132
 
108
133
  websocket.receive({msg: 'logged_message'}.to_json)
109
134
 
@@ -115,7 +140,7 @@ describe Metybur do
115
140
  it 'subscribes to a published record set' do
116
141
  record_set = FFaker::Internet.user_name
117
142
 
118
- meteor = Metybur.connect url
143
+ meteor = Metybur.connect(url)
119
144
  meteor.subscribe(record_set)
120
145
 
121
146
  expect(last_sent_message[:msg]).to eq 'sub'
@@ -125,20 +150,12 @@ describe Metybur do
125
150
  end
126
151
 
127
152
  context 'collections' do
128
- def wait_for_callback(options = {})
129
- calls = options[:calls] || 1 # No keyword arguments in Ruby 1.9.3
130
- times_called = 0
131
- done = -> { times_called += 1 }
132
- yield done
133
- fail("Callback only got called #{times_called} time(s).") if times_called < calls
134
- end
135
-
136
153
  it 'gets notified when a record is added' do
137
154
  collection = FFaker::Internet.user_name
138
155
  id = FFaker::Guid.guid
139
156
  fields = {city: FFaker::Address.city}
140
157
 
141
- meteor = Metybur.connect url
158
+ meteor = Metybur.connect(url)
142
159
 
143
160
  wait_for_callback do |done|
144
161
  meteor.collection(collection)
@@ -164,7 +181,7 @@ describe Metybur do
164
181
  fields = {city: FFaker::Address.city}
165
182
  cleared = [FFaker::Guid.guid]
166
183
 
167
- meteor = Metybur.connect url
184
+ meteor = Metybur.connect(url)
168
185
 
169
186
  wait_for_callback do |done|
170
187
  meteor.collection(collection)
@@ -190,7 +207,7 @@ describe Metybur do
190
207
  collection = FFaker::Internet.user_name
191
208
  id = FFaker::Guid.guid
192
209
 
193
- meteor = Metybur.connect url
210
+ meteor = Metybur.connect(url)
194
211
 
195
212
  wait_for_callback do |done|
196
213
  meteor.collection(collection)
@@ -223,7 +240,7 @@ describe Metybur do
223
240
  id = FFaker::Guid.guid
224
241
  fields = {city: FFaker::Address.city}
225
242
 
226
- meteor = Metybur.connect url
243
+ meteor = Metybur.connect(url)
227
244
 
228
245
  wait_for_callback(calls: 2) do |done|
229
246
  meteor.collection(collection)
@@ -299,5 +316,56 @@ describe Metybur do
299
316
  expect(last_sent_message).to have_key :id # we don't care about the value here
300
317
  expect(last_sent_message[:params]).to eq ['Hans', {userId: 'utrtrvlc', isAdmin: false}]
301
318
  end
319
+
320
+ it 'passes the result to a block' do
321
+ meteor = Metybur.connect(url)
322
+
323
+ wait_for_callback do |done|
324
+ meteor.get_product(27) do |product|
325
+ done.call
326
+ expect(product[:price]).to eq 99
327
+ end
328
+
329
+ id = last_sent_message[:id]
330
+ websocket.receive({
331
+ msg: 'result',
332
+ id: id,
333
+ result: {price: 99}
334
+ }.to_json)
335
+ end
336
+ end
337
+
338
+ it "doesn't trigger the callback for ping messages" do
339
+ meteor = Metybur.connect(url)
340
+
341
+ meteor.get_product(27) do |product|
342
+ fail
343
+ end
344
+
345
+ websocket.receive({msg: 'ping'}.to_json)
346
+ end
347
+
348
+ it 'triggers the callback with the right result' do
349
+ meteor = Metybur.connect(url)
350
+
351
+ wait_for_callback do |done|
352
+ meteor.get_product(27) do |product|
353
+ done.call
354
+ expect(product[:price]).to eq 99
355
+ end
356
+
357
+ id = last_sent_message[:id]
358
+ websocket.receive({
359
+ msg: 'result',
360
+ id: 'abc',
361
+ result: {price: 19}
362
+ }.to_json)
363
+ websocket.receive({
364
+ msg: 'result',
365
+ id: id,
366
+ result: {price: 99}
367
+ }.to_json)
368
+ end
369
+ end
302
370
  end
303
371
  end
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.1.1
4
+ version: 0.2.0
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-08 00:00:00.000000000 Z
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -128,6 +128,7 @@ files:
128
128
  - lib/metybur.rb
129
129
  - lib/metybur/client.rb
130
130
  - lib/metybur/collection.rb
131
+ - lib/metybur/method.rb
131
132
  - lib/metybur/version.rb
132
133
  - metybur.gemspec
133
134
  - spec/metybur_spec.rb