metybur 0.0.1 → 0.1.0

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: 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.