entangled 0.0.20 → 0.0.21

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