entangled 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,7 +10,6 @@ angular.module('entangledTest')
10
10
  Message.find($routeParams.id, function(message) {
11
11
  $scope.$apply(function() {
12
12
  $scope.message = message;
13
- console.log('Show callback called!');
14
13
  });
15
14
  });
16
15
  });
@@ -9,7 +9,7 @@ angular.module('entangled', [])
9
9
  // methods $save() and $destroy. A Resource also
10
10
  // stores the socket's URL it was retrieved from so it
11
11
  // can be reused for other requests.
12
- var Resource = function(params, webSocketUrl) {
12
+ var Resource = function(params, webSocketUrl, hasMany) {
13
13
  // Assign proerties
14
14
  for (var key in params) {
15
15
  // Skip inherent object properties
@@ -18,7 +18,15 @@ angular.module('entangled', [])
18
18
  }
19
19
  }
20
20
 
21
+ // Assign socket URL
21
22
  this.webSocketUrl = webSocketUrl;
23
+
24
+ // Assign has many relationship
25
+ if (hasMany) {
26
+ this[hasMany] = function() {
27
+ return new Entangled(this.webSocketUrl + '/' + this.id + '/' + hasMany);
28
+ };
29
+ }
22
30
  };
23
31
 
24
32
  // $save() will send a request to the server
@@ -26,14 +34,12 @@ angular.module('entangled', [])
26
34
  // an existing, depending on whether or not
27
35
  // an id is present.
28
36
  Resource.prototype.$save = function(callback) {
29
- var that = this;
30
-
31
37
  if (this.id) {
32
38
  // Update
33
- var socket = new WebSocket(that.webSocketUrl + '/' + that.id + '/update');
39
+ var socket = new WebSocket(this.webSocketUrl + '/' + this.id + '/update');
34
40
  socket.onopen = function() {
35
- socket.send(JSON.stringify(that));
36
- };
41
+ socket.send(JSON.stringify(this));
42
+ }.bind(this);
37
43
 
38
44
  // Receive updated resource from server
39
45
  socket.onmessage = function(event) {
@@ -43,25 +49,29 @@ angular.module('entangled', [])
43
49
  // Assign/override new data (such as updated_at, etc)
44
50
  if (data.resource) {
45
51
  for (key in data.resource) {
46
- that[key] = data.resource[key];
52
+ this[key] = data.resource[key];
47
53
  }
48
54
  }
49
55
  }
50
56
 
51
- // Pass 'that' to callback for create
52
- // function so that the create function
57
+ // Assign has many association. The association
58
+ // can only be available to a persisted record
59
+ this[this.hasMany] = new Entangled(this.webSocketUrl + '/' + this.id + '/' + this.hasMany);
60
+
61
+ // Pass 'this' to callback for create
62
+ // function so this the create function
53
63
  // can pass the created resource to its
54
64
  // own callback; not needed for $save per se
55
- if (callback) callback(that);
56
- };
65
+ if (callback) callback(this);
66
+ }.bind(this);
57
67
  } else {
58
68
  // Create
59
- var socket = new WebSocket(that.webSocketUrl + '/create');
69
+ var socket = new WebSocket(this.webSocketUrl + '/create');
60
70
 
61
71
  // Send attributes to server
62
72
  socket.onopen = function() {
63
- socket.send(JSON.stringify(that));
64
- };
73
+ socket.send(JSON.stringify(this));
74
+ }.bind(this);
65
75
 
66
76
  // Receive saved resource from server
67
77
  socket.onmessage = function(event) {
@@ -72,17 +82,17 @@ angular.module('entangled', [])
72
82
  // updated_at, etc)
73
83
  if (data.resource) {
74
84
  for (key in data.resource) {
75
- that[key] = data.resource[key];
85
+ this[key] = data.resource[key];
76
86
  }
77
87
  }
78
88
  }
79
89
 
80
- // Pass 'that' to callback for create
81
- // function so that the create function
90
+ // Pass 'this' to callback for create
91
+ // function so this the create function
82
92
  // can pass the created resource to its
83
93
  // own callback; not needed for $save per se
84
- if (callback) callback(that);
85
- };
94
+ if (callback) callback(this);
95
+ }.bind(this);
86
96
  }
87
97
  };
88
98
 
@@ -136,11 +146,11 @@ angular.module('entangled', [])
136
146
 
137
147
  // Resources wraps all individual Resource objects
138
148
  // in a collection.
139
- var Resources = function(resources, webSocketUrl) {
149
+ var Resources = function(resources, webSocketUrl, hasMany) {
140
150
  this.all = [];
141
151
 
142
152
  for (var i = 0; i < resources.length; i++) {
143
- var resource = new Resource(resources[i], webSocketUrl);
153
+ var resource = new Resource(resources[i], webSocketUrl, hasMany);
144
154
  this.all.push(resource);
145
155
  }
146
156
  };
@@ -160,10 +170,17 @@ angular.module('entangled', [])
160
170
  this.webSocketUrl = webSocketUrl;
161
171
  };
162
172
 
173
+ // hasMany() adds the appropriate association and
174
+ // sets up websockets accordingly
175
+ Entangled.prototype.hasMany = function(resources) {
176
+ this.hasMany = resources;
177
+ // this[resources] = new Entangled(this.webSocketUrl + '/' + this.id + '/' + resources);
178
+ };
179
+
163
180
  // Function to instantiate a new Resource, optionally
164
181
  // with given parameters
165
182
  Entangled.prototype.new = function(params) {
166
- return new Resource(params, this.webSocketUrl);
183
+ return new Resource(params, this.webSocketUrl, this.hasMany);
167
184
  };
168
185
 
169
186
  // Retrieve all Resources from the root of the socket's
@@ -180,12 +197,12 @@ angular.module('entangled', [])
180
197
  // If the collection of Resources was sent
181
198
  if (data.resources) {
182
199
  // Store retrieved Resources in property
183
- this.resources = new Resources(data.resources, socket.url);
200
+ this.resources = new Resources(data.resources, socket.url, this.hasMany);
184
201
  } else if (data.action) {
185
202
  if (data.action === 'create') {
186
203
  // If new Resource was created, add it to the
187
204
  // collection
188
- this.resources.all.push(new Resource(data.resource, socket.url));
205
+ this.resources.all.push(new Resource(data.resource, socket.url, this.hasMany));
189
206
  } else if (data.action === 'update') {
190
207
  // If an existing Resource was updated,
191
208
  // update it in the collection as well
@@ -197,7 +214,7 @@ angular.module('entangled', [])
197
214
  }
198
215
  }
199
216
 
200
- this.resources.all[index] = new Resource(data.resource, socket.url);
217
+ this.resources.all[index] = new Resource(data.resource, socket.url, this.hasMany);
201
218
  } else if (data.action === 'destroy') {
202
219
  // If a Resource was destroyed, remove it
203
220
  // from Resources as well
@@ -220,7 +237,7 @@ angular.module('entangled', [])
220
237
  // Run the callback and pass in the
221
238
  // resulting collection
222
239
  callback(this.resources.all);
223
- };
240
+ }.bind(this);
224
241
  };
225
242
 
226
243
  // Instantiate and persist a record in one go
@@ -243,12 +260,12 @@ angular.module('entangled', [])
243
260
  if (data.resource && !data.action) {
244
261
  // If the Resource was sent from the server,
245
262
  // store it
246
- this.resource = new Resource(data.resource, webSocketUrl);
263
+ this.resource = new Resource(data.resource, webSocketUrl, this.hasMany);
247
264
  } else if (data.action) {
248
265
  if (data.action === 'update') {
249
266
  // If the stored Resource was updated,
250
267
  // update it here as well
251
- this.resource = new Resource(data.resource, webSocketUrl);
268
+ this.resource = new Resource(data.resource, webSocketUrl, this.hasMany);
252
269
  } else if (data.action === 'destroy') {
253
270
  // If the stored Resource was destroyed,
254
271
  // remove it from here as well
@@ -262,7 +279,7 @@ angular.module('entangled', [])
262
279
 
263
280
  // Run callback with retrieved Resource
264
281
  callback(this.resource);
265
- };
282
+ }.bind(this);
266
283
  };
267
284
 
268
285
  return Entangled;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ angular.module('entangledTest')
4
+
5
+ .factory('List', function(Entangled) {
6
+ var entangled = new Entangled('ws://localhost:3000/lists');
7
+ entangled.hasMany('items');
8
+ return entangled;
9
+ });
@@ -11,6 +11,9 @@
11
11
  <script src="app/app.js"></script>
12
12
  <script src="app/controllers/messages.js"></script>
13
13
  <script src="app/controllers/message.js"></script>
14
+ <script src="app/controllers/lists.js"></script>
15
+ <script src="app/controllers/list.js"></script>
14
16
  <script src="app/services/message.js"></script>
17
+ <script src="app/services/list.js"></script>
15
18
  </body>
16
19
  </html>
@@ -0,0 +1,87 @@
1
+ 'use strict';
2
+
3
+ describe('ListsCtrl', function() {
4
+ beforeEach(module('entangledTest'));
5
+
6
+ var ListsCtrl,
7
+ scope,
8
+ List;
9
+
10
+ beforeEach(inject(function ($controller, $rootScope, $injector) {
11
+ scope = $rootScope.$new();
12
+ ListsCtrl = $controller('ListsCtrl', {
13
+ $scope: scope
14
+ }),
15
+ List = $injector.get('List');
16
+ }));
17
+
18
+ it('fetches all lists', function(done) {
19
+ List.all(function(lists) {
20
+ expect(lists).toEqual(jasmine.any(Array));
21
+ done();
22
+ });
23
+ });
24
+
25
+ it("fetches a list's items after creating it", function(done) {
26
+ List.create({ name: 'foo' }, function(list) {
27
+ // Assert that list has been persisted
28
+ expect(list.$persisted()).toBeTruthy();
29
+
30
+ // Fetch list's items
31
+ list.items().all(function(items) {
32
+ expect(items).toEqual(jasmine.any(Array));
33
+ done();
34
+ });
35
+ });
36
+ });
37
+
38
+ it("fetches a list's items after fetching it", function(done) {
39
+ List.create({ name: 'foo' }, function(list) {
40
+ // Fetch list
41
+ List.find(list.id, function(list) {
42
+ // Assert that list is persisted
43
+ expect(list.$persisted).toBeTruthy();
44
+
45
+ // Fetch list's items
46
+ list.items().all(function(items) {
47
+ expect(items).toEqual(jasmine.any(Array));
48
+ done();
49
+ });
50
+ });
51
+ });
52
+ });
53
+
54
+ it("fetches a list's items when fetching all lists", function(done) {
55
+ List.all(function(lists) {
56
+ var list = lists[0];
57
+
58
+ // Assert that list is persisted
59
+ expect(list.$persisted()).toBeTruthy();
60
+
61
+ // Fetch list's items
62
+ list.items().all(function(items) {
63
+ expect(items).toEqual(jasmine.any(Array));
64
+ done();
65
+ });
66
+ });
67
+ });
68
+
69
+ it("creates and finds a list's item", function(done) {
70
+ List.create({ name: 'foo' }, function(list) {
71
+ // Create item
72
+ list.items().create({ name: 'foo' }, function(item) {
73
+ // Assert that item has been persisted
74
+ expect(item.$persisted()).toBeTruthy();
75
+
76
+ // Assert that item's list_id is equal to the list's id
77
+ expect(item.list_id).toBe(list.id);
78
+
79
+ // Assert that it can find the item
80
+ list.items().find(item.id, function(item) {
81
+ expect(item.$persisted()).toBeTruthy();
82
+ done();
83
+ });
84
+ });
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,14 @@
1
+ <h1>Lists</h1>
2
+
3
+ <table>
4
+ <tr ng-repeat="list in lists">
5
+ <td><a ng-href="#/lists/{{ list.id }}">{{ list.name }}</a></td>
6
+ <td><button ng-click="destroy(list)">Delete</button></td>
7
+ </li>
8
+ </table>
9
+
10
+ <form ng-submit="create()">
11
+ <input type="text" ng-model="list.name">
12
+ <input type="submit">
13
+ </form>
14
+
@@ -0,0 +1,9 @@
1
+ <h1>List</h1>
2
+
3
+ <h2>{{ list.name }}</h2>
4
+
5
+ <ul>
6
+ <li ng-repeat="item in items">
7
+ {{ item.name }}, {{ item.complete }}
8
+ </li>
9
+ </ul>
@@ -16,7 +16,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
16
16
 
17
17
  # Publishing to collection channel
18
18
  expect(redis).to have_received(:publish).with(
19
- 'foos', {
19
+ foo.collection_channel, {
20
20
  action: :create,
21
21
  resource: foo
22
22
  }.to_json
@@ -24,7 +24,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
24
24
 
25
25
  # Publishing to member channel
26
26
  expect(redis).to have_received(:publish).with(
27
- "foos/#{foo.to_param}", {
27
+ foo.member_channel, {
28
28
  action: :create,
29
29
  resource: foo
30
30
  }.to_json
@@ -44,7 +44,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
44
44
  ).never
45
45
 
46
46
  expect(redis).to have_received(:publish).with(
47
- "foos/#{foo.to_param}", {
47
+ foo.member_channel, {
48
48
  action: :update,
49
49
  resource: foo
50
50
  }.to_json
@@ -64,7 +64,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
64
64
  ).never
65
65
 
66
66
  expect(redis).to have_received(:publish).with(
67
- "foos/#{foo.to_param}", {
67
+ foo.member_channel, {
68
68
  action: :destroy,
69
69
  resource: foo
70
70
  }.to_json
@@ -80,7 +80,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
80
80
 
81
81
  # Publishing to collection channel
82
82
  expect(redis).to have_received(:publish).with(
83
- 'bars', {
83
+ bar.collection_channel, {
84
84
  action: :create,
85
85
  resource: bar
86
86
  }.to_json
@@ -88,7 +88,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
88
88
 
89
89
  # Publishing to member channel
90
90
  expect(redis).to have_received(:publish).with(
91
- "bars/#{bar.to_param}", {
91
+ bar.member_channel, {
92
92
  action: :create,
93
93
  resource: bar
94
94
  }.to_json
@@ -101,14 +101,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
101
101
  bar.update(body: 'bar')
102
102
 
103
103
  expect(redis).to have_received(:publish).with(
104
- 'bars', {
104
+ bar.collection_channel, {
105
105
  action: :update,
106
106
  resource: bar
107
107
  }.to_json
108
108
  )
109
109
 
110
110
  expect(redis).to have_received(:publish).with(
111
- "bars/#{bar.to_param}", {
111
+ bar.member_channel, {
112
112
  action: :update,
113
113
  resource: bar
114
114
  }.to_json
@@ -121,14 +121,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
121
121
  bar.destroy
122
122
 
123
123
  expect(redis).to have_received(:publish).with(
124
- 'bars', {
124
+ bar.collection_channel, {
125
125
  action: :destroy,
126
126
  resource: bar
127
127
  }.to_json
128
128
  ).never
129
129
 
130
130
  expect(redis).to have_received(:publish).with(
131
- "bars/#{bar.to_param}", {
131
+ bar.member_channel, {
132
132
  action: :destroy,
133
133
  resource: bar
134
134
  }.to_json
@@ -144,7 +144,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
144
144
 
145
145
  # Publishing to collection channel
146
146
  expect(redis).to have_received(:publish).with(
147
- 'foobars', {
147
+ foobar.collection_channel, {
148
148
  action: :create,
149
149
  resource: foobar
150
150
  }.to_json
@@ -152,7 +152,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
152
152
 
153
153
  # Publishing to member channel
154
154
  expect(redis).to have_received(:publish).with(
155
- "foobars/#{foobar.to_param}", {
155
+ foobar.member_channel, {
156
156
  action: :create,
157
157
  resource: foobar
158
158
  }.to_json
@@ -165,14 +165,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
165
165
  foobar.update(body: 'foobar')
166
166
 
167
167
  expect(redis).to have_received(:publish).with(
168
- 'foobars', {
168
+ foobar.collection_channel, {
169
169
  action: :update,
170
170
  resource: foobar
171
171
  }.to_json
172
172
  )
173
173
 
174
174
  expect(redis).to have_received(:publish).with(
175
- "foobars/#{foobar.to_param}", {
175
+ foobar.member_channel, {
176
176
  action: :update,
177
177
  resource: foobar
178
178
  }.to_json
@@ -185,14 +185,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
185
185
  foobar.destroy
186
186
 
187
187
  expect(redis).to have_received(:publish).with(
188
- 'foobars', {
188
+ foobar.collection_channel, {
189
189
  action: :destroy,
190
190
  resource: foobar
191
191
  }.to_json
192
192
  )
193
193
 
194
194
  expect(redis).to have_received(:publish).with(
195
- "foobars/#{foobar.to_param}", {
195
+ foobar.member_channel, {
196
196
  action: :destroy,
197
197
  resource: foobar
198
198
  }.to_json
@@ -208,7 +208,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
208
208
 
209
209
  # Publishing to collection channel
210
210
  expect(redis).to have_received(:publish).with(
211
- 'barfoos', {
211
+ barfoo.collection_channel, {
212
212
  action: :create,
213
213
  resource: barfoo
214
214
  }.to_json
@@ -216,7 +216,7 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
216
216
 
217
217
  # Publishing to member channel
218
218
  expect(redis).to have_received(:publish).with(
219
- "barfoos/#{barfoo.to_param}", {
219
+ barfoo.member_channel, {
220
220
  action: :create,
221
221
  resource: barfoo
222
222
  }.to_json
@@ -229,14 +229,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
229
229
  barfoo.update(body: 'barfoo')
230
230
 
231
231
  expect(redis).to have_received(:publish).with(
232
- 'barfoos', {
232
+ barfoo.collection_channel, {
233
233
  action: :update,
234
234
  resource: barfoo
235
235
  }.to_json
236
236
  ).never
237
237
 
238
238
  expect(redis).to have_received(:publish).with(
239
- "barfoos/#{barfoo.to_param}", {
239
+ barfoo.member_channel, {
240
240
  action: :update,
241
241
  resource: barfoo
242
242
  }.to_json
@@ -249,14 +249,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
249
249
  barfoo.destroy
250
250
 
251
251
  expect(redis).to have_received(:publish).with(
252
- 'barfoos', {
252
+ barfoo.collection_channel, {
253
253
  action: :destroy,
254
254
  resource: barfoo
255
255
  }.to_json
256
256
  ).never
257
257
 
258
258
  expect(redis).to have_received(:publish).with(
259
- "barfoos/#{barfoo.to_param}", {
259
+ barfoo.member_channel, {
260
260
  action: :destroy,
261
261
  resource: barfoo
262
262
  }.to_json