metybur 0.0.1 → 0.1.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: 2043abcd1c4c248fdf3e2a7981a4b68aed1c248d
4
- data.tar.gz: a44a7514d74dcdbdb571d80804db938deba29bf8
3
+ metadata.gz: 16de5f618ad1003be841607f85eba295cf4bb6ae
4
+ data.tar.gz: bd1dc5ca319577920cf96f22109eb61446b07b24
5
5
  SHA512:
6
- metadata.gz: bfded496cb0f109c29daac6a401001499ba7f698c47e9358a2d2e8116fdacf9f88cc807b4608786e6c079fb4a2099335f431babfc87c8825c492173dceca0d6b
7
- data.tar.gz: 1bc3b6fc5afb48f64b552a7006ec84680bd0c6efa8b2df70ea4580db64fdb96e2db830dfb6de82851729392589c5bcf253e85890c06c9e5f66327d4c949fc46d
6
+ metadata.gz: 0c9ddb24c0714374d16e2d55b92721127e65c3a7603aa78e86ae6a8148a66d870867f99ff539088558acadc836023d7be75fbf7009327c9138f7289326ef493f
7
+ data.tar.gz: 36b0c96d11d27111276dc932387987280409b72011e2a2f585ce75887da72ff44d0929977c39a1b3c5c5905c9da42a157dd0f9e8d371e50bf7a1830bfcbb0860
data/README.md CHANGED
@@ -34,7 +34,7 @@ Or install it yourself as:
34
34
  ### Connecting to a Meteor app
35
35
 
36
36
  Metybur runs in an [EventMachine](http://eventmachine.rubyforge.org/) loop.
37
- Therefore all our code must be wrapped in an `EM.run` block.
37
+ Therefore all your code must be wrapped in an `EM.run` block.
38
38
 
39
39
  ```ruby
40
40
  require 'eventmachine'
@@ -93,6 +93,23 @@ Once you've subscribed, you will receive all records that are already in the rec
93
93
  @chat_messages = {}
94
94
  meteor.collection('chat-messages')
95
95
  .on(:added) { |id, attributes| @chat_messages[id] = attributes }
96
+ .on(:changed) { |id, attributes, cleared|
97
+ chat_message = @chat_messages[id]
98
+ chat_message.merge!(attributes)
99
+ cleared.each { |field| chat_message.delete(field) }
100
+ }
101
+ .on(:removed) { |id| @chat_messages.delete(id) }
102
+ ```
103
+
104
+ You can also assign multiple callbacks to one event:
105
+
106
+ ```ruby
107
+ @chat_messages = {}
108
+ collection = meteor.collection('chat-messages')
109
+
110
+ collection.on(:added) { |id, attributes| @chat_messages[id] = attributes }
111
+
112
+ collection.on(:added) { |id, attributes| puts "received message #{attributes[:text]}" }
96
113
  ```
97
114
 
98
115
  ### Remote Procedure Calls
@@ -107,9 +124,11 @@ This corresponds to the following method call in Meteor:
107
124
 
108
125
  ```javascript
109
126
  // Javascript
110
- Meteor.call('postChatMessage', { inRoom: 'General' });
127
+ Meteor.call('postChatMessage', ['Hey there!', { inRoom: 'General' }]);
111
128
  ```
112
129
 
130
+ Methods and hash keys will be camel-cased for you, so you can stick to the Ruby naming convention.
131
+
113
132
  If you prefer the Meteor syntax, you can also call the method like this:
114
133
 
115
134
  ```ruby
@@ -1,14 +1,24 @@
1
1
  class Metybur::Collection
2
2
  def initialize(collection_name, websocket)
3
+ @callbacks = {}
4
+
3
5
  websocket.on(:message) do |event|
4
6
  attributes = JSON.parse(event.data, symbolize_names: true)
5
- if attributes[:msg] == 'added' && attributes[:collection] == collection_name
6
- @added_callback.call(attributes[:id], attributes[:fields])
7
- end
7
+ handle_message(attributes) if attributes[:collection] == collection_name
8
8
  end
9
9
  end
10
10
 
11
11
  def on(event, &block)
12
- @added_callback = block
12
+ @callbacks[event] ||= []
13
+ @callbacks[event] << block
14
+ self
15
+ end
16
+
17
+ private
18
+
19
+ def handle_message(attributes)
20
+ event = attributes[:msg].to_sym
21
+ arguments = attributes.slice(:id, :fields, :cleared).values
22
+ @callbacks[event].each { |callback| callback.call(*arguments) }
13
23
  end
14
24
  end
@@ -1,3 +1,3 @@
1
1
  module Metybur
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/metybur.rb CHANGED
@@ -44,20 +44,7 @@ module Metybur
44
44
 
45
45
  password = credentials.delete(:password)
46
46
  return client unless password
47
-
48
- login_message = {
49
- msg: 'method',
50
- id: 'abc',
51
- method: 'login',
52
- params: [
53
- {
54
- user: credentials,
55
- password: password
56
- }
57
- ]
58
- }
59
-
60
- websocket.send(login_message.to_json)
47
+ client.login(user: credentials, password: password)
61
48
 
62
49
  client
63
50
  end
data/spec/metybur_spec.rb CHANGED
@@ -10,6 +10,7 @@ describe Metybur do
10
10
 
11
11
  let(:url) { FFaker::Internet.http_url }
12
12
  let(:websocket) { WebsocketMock.instance }
13
+ let(:last_sent_message) { parse(websocket.sent.last) }
13
14
 
14
15
  def parse(string_data)
15
16
  JSON.parse(string_data, symbolize_names: true)
@@ -33,11 +34,10 @@ describe Metybur do
33
34
 
34
35
  Metybur.connect url, email: email, password: password
35
36
 
36
- login_message = parse(websocket.sent.last)
37
- expect(login_message[:msg]).to eq 'method'
38
- expect(login_message).to have_key :id # we don't care about the value here
39
- expect(login_message[:method]).to eq 'login'
40
- expect(login_message[:params][0])
37
+ expect(last_sent_message[:msg]).to eq 'method'
38
+ expect(last_sent_message).to have_key :id # we don't care about the value here
39
+ expect(last_sent_message[:method]).to eq 'login'
40
+ expect(last_sent_message[:params][0])
41
41
  .to eq user: { email: email },
42
42
  password: password
43
43
  end
@@ -48,11 +48,10 @@ describe Metybur do
48
48
 
49
49
  Metybur.connect url, username: username, password: password
50
50
 
51
- login_message = parse(websocket.sent.last)
52
- expect(login_message[:msg]).to eq 'method'
53
- expect(login_message).to have_key :id # we don't care about the value here
54
- expect(login_message[:method]).to eq 'login'
55
- expect(login_message[:params][0])
51
+ expect(last_sent_message[:msg]).to eq 'method'
52
+ expect(last_sent_message).to have_key :id # we don't care about the value here
53
+ expect(last_sent_message[:method]).to eq 'login'
54
+ expect(last_sent_message[:params][0])
56
55
  .to eq user: { username: username },
57
56
  password: password
58
57
  end
@@ -63,11 +62,10 @@ describe Metybur do
63
62
 
64
63
  Metybur.connect url, id: userid, password: password
65
64
 
66
- login_message = parse(websocket.sent.last)
67
- expect(login_message[:msg]).to eq 'method'
68
- expect(login_message).to have_key :id # we don't care about the value here
69
- expect(login_message[:method]).to eq 'login'
70
- expect(login_message[:params][0])
65
+ expect(last_sent_message[:msg]).to eq 'method'
66
+ expect(last_sent_message).to have_key :id # we don't care about the value here
67
+ expect(last_sent_message[:method]).to eq 'login'
68
+ expect(last_sent_message[:params][0])
71
69
  .to eq user: { id: userid },
72
70
  password: password
73
71
  end
@@ -75,8 +73,7 @@ describe Metybur do
75
73
  it "doesn't log in without credentials" do
76
74
  Metybur.connect url
77
75
 
78
- last_message = parse(websocket.sent.last)
79
- expect(last_message[:msg]).to eq 'connect'
76
+ expect(last_sent_message[:msg]).to eq 'connect'
80
77
  end
81
78
  end
82
79
 
@@ -86,8 +83,7 @@ describe Metybur do
86
83
 
87
84
  websocket.receive({msg: 'ping'}.to_json)
88
85
 
89
- last_message = parse(websocket.sent.last)
90
- expect(last_message[:msg]).to eq 'pong'
86
+ expect(last_sent_message[:msg]).to eq 'pong'
91
87
  end
92
88
  end
93
89
 
@@ -122,38 +118,125 @@ describe Metybur do
122
118
  meteor = Metybur.connect url
123
119
  meteor.subscribe(record_set)
124
120
 
125
- last_message = parse(websocket.sent.last)
126
- expect(last_message[:msg]).to eq 'sub'
127
- expect(last_message).to have_key :id # we don't care about the value here
128
- expect(last_message[:name]).to eq record_set
121
+ expect(last_sent_message[:msg]).to eq 'sub'
122
+ expect(last_sent_message).to have_key :id # we don't care about the value here
123
+ expect(last_sent_message[:name]).to eq record_set
129
124
  end
130
125
  end
131
126
 
132
127
  context 'collections' do
128
+ def wait_for_callback(calls: 1)
129
+ times_called = 0
130
+ done = -> { times_called += 1 }
131
+ yield done
132
+ fail("Callback only got called #{times_called} time(s).") if times_called < calls
133
+ end
134
+
133
135
  it 'gets notified when a record is added' do
134
136
  collection = FFaker::Internet.user_name
135
- callback_called = false
137
+ id = FFaker::Guid.guid
138
+ fields = {city: FFaker::Address.city}
139
+
140
+ meteor = Metybur.connect url
141
+
142
+ wait_for_callback do |done|
143
+ meteor.collection(collection)
144
+ .on(:added) do |added_id, added_fields|
145
+ done.call()
146
+ expect(added_id).to eq id
147
+ expect(added_fields).to eq fields
148
+ end
149
+
150
+ message = {
151
+ msg: 'added',
152
+ collection: collection,
153
+ id: id,
154
+ fields: fields
155
+ }.to_json
156
+ websocket.receive message
157
+ end
158
+ end
136
159
 
160
+ it 'gets notified when a record is changed' do
161
+ collection = FFaker::Internet.user_name
137
162
  id = FFaker::Guid.guid
138
163
  fields = {city: FFaker::Address.city}
164
+ cleared = [FFaker::Guid.guid]
139
165
 
140
166
  meteor = Metybur.connect url
141
- meteor.collection(collection)
142
- .on(:added) do |added_id, added_fields|
143
- callback_called = true
144
- expect(added_id).to eq id
145
- expect(added_fields).to eq fields
146
- end
147
167
 
148
- message = {
149
- msg: 'added',
150
- collection: collection,
151
- id: id,
152
- fields: fields
153
- }.to_json
154
- websocket.receive message
168
+ wait_for_callback do |done|
169
+ meteor.collection(collection)
170
+ .on(:changed) do |changed_id, changed_fields, cleared_fields|
171
+ done.call()
172
+ expect(changed_id).to eq id
173
+ expect(changed_fields).to eq fields
174
+ expect(cleared_fields).to eq cleared
175
+ end
176
+
177
+ message = {
178
+ msg: 'changed',
179
+ collection: collection,
180
+ id: id,
181
+ fields: fields,
182
+ cleared: cleared
183
+ }.to_json
184
+ websocket.receive message
185
+ end
186
+ end
187
+
188
+ it 'gets notified when a record is removed' do
189
+ collection = FFaker::Internet.user_name
190
+ id = FFaker::Guid.guid
191
+
192
+ meteor = Metybur.connect url
193
+
194
+ wait_for_callback do |done|
195
+ meteor.collection(collection)
196
+ .on(:removed) do |removed_id|
197
+ done.call()
198
+ expect(removed_id).to eq id
199
+ end
200
+
201
+ message = {
202
+ msg: 'removed',
203
+ collection: collection,
204
+ id: id
205
+ }.to_json
206
+ websocket.receive message
207
+ end
208
+ end
209
+
210
+ it 'lets the `on` method be chainable' do
211
+ meteor = Metybur.connect(url)
212
+ meteor.collection('my-collection')
213
+ .on(:added) { anything }
214
+ .on(:changed) { anything }
215
+ .on(:removed) { anything }
216
+
217
+ # Succeeds if there is no error
218
+ end
219
+
220
+ it 'registers multiple added callbacks' do
221
+ collection = FFaker::Internet.user_name
222
+ id = FFaker::Guid.guid
223
+ fields = {city: FFaker::Address.city}
224
+
225
+ meteor = Metybur.connect url
155
226
 
156
- fail("Callback didn't get called.") unless callback_called
227
+ wait_for_callback(calls: 2) do |done|
228
+ meteor.collection(collection)
229
+ .on(:added) { |added_id, added_fields| done.call() }
230
+ .on(:added) { |added_id, added_fields| done.call() }
231
+
232
+ message = {
233
+ msg: 'added',
234
+ collection: collection,
235
+ id: id,
236
+ fields: fields
237
+ }.to_json
238
+ websocket.receive message
239
+ end
157
240
  end
158
241
 
159
242
  it "doesn't get notified of a ping message" do
@@ -190,33 +273,30 @@ describe Metybur do
190
273
  meteor = Metybur.connect(url)
191
274
  meteor.call(method, params)
192
275
 
193
- last_message = parse(websocket.sent.last)
194
- expect(last_message[:msg]).to eq 'method'
195
- expect(last_message[:method]).to eq method
196
- expect(last_message).to have_key :id # we don't care about the value here
197
- expect(last_message[:params]).to eq params
276
+ expect(last_sent_message[:msg]).to eq 'method'
277
+ expect(last_sent_message[:method]).to eq method
278
+ expect(last_sent_message).to have_key :id # we don't care about the value here
279
+ expect(last_sent_message[:params]).to eq params
198
280
  end
199
281
 
200
282
  it 'calls a method called on the client directly' do
201
283
  meteor = Metybur.connect(url)
202
284
  meteor.activate('user', id: 'utrtrvlc')
203
285
 
204
- last_message = parse(websocket.sent.last)
205
- expect(last_message[:msg]).to eq 'method'
206
- expect(last_message[:method]).to eq 'activate'
207
- expect(last_message).to have_key :id # we don't care about the value here
208
- expect(last_message[:params]).to eq ['user', {id: 'utrtrvlc'}]
286
+ expect(last_sent_message[:msg]).to eq 'method'
287
+ expect(last_sent_message[:method]).to eq 'activate'
288
+ expect(last_sent_message).to have_key :id # we don't care about the value here
289
+ expect(last_sent_message[:params]).to eq ['user', {id: 'utrtrvlc'}]
209
290
  end
210
291
 
211
292
  it 'camel-cases methods and parameters called on the client directly' do
212
293
  meteor = Metybur.connect(url)
213
294
  meteor.activate_user('Hans', user_id: 'utrtrvlc', is_admin: false)
214
295
 
215
- last_message = parse(websocket.sent.last)
216
- expect(last_message[:msg]).to eq 'method'
217
- expect(last_message[:method]).to eq 'activateUser'
218
- expect(last_message).to have_key :id # we don't care about the value here
219
- expect(last_message[:params]).to eq ['Hans', {userId: 'utrtrvlc', isAdmin: false}]
296
+ expect(last_sent_message[:msg]).to eq 'method'
297
+ expect(last_sent_message[:method]).to eq 'activateUser'
298
+ expect(last_sent_message).to have_key :id # we don't care about the value here
299
+ expect(last_sent_message[:params]).to eq ['Hans', {userId: 'utrtrvlc', isAdmin: false}]
220
300
  end
221
301
  end
222
302
  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.0.1
4
+ version: 0.1.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-05 00:00:00.000000000 Z
11
+ date: 2015-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  version: '0'
154
154
  requirements: []
155
155
  rubyforge_project:
156
- rubygems_version: 2.4.5
156
+ rubygems_version: 2.2.2
157
157
  signing_key:
158
158
  specification_version: 4
159
159
  summary: DDP client for Ruby to connect to Meteor apps.