entangled 0.0.17 → 0.0.18

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: 620c93edc4a4892c41fe62cfd60cd448a245621e
4
- data.tar.gz: d0cde74b9d171662e6bb716349a80eedcf943441
3
+ metadata.gz: c26b49537871a591ca346338518c72959721f39a
4
+ data.tar.gz: b1edc3cd5f06358c30ce85ef8146da53db890704
5
5
  SHA512:
6
- metadata.gz: 24ee4a89da4c1ff4dd462ea2b34f335cb9c05aea74488a6682e6ab6959e0388b3894262ff4adde9f15896c039f8de9a9015d0cce61e794e7a91fa322771493d0
7
- data.tar.gz: 34d56b6e058a103daa410ca346e01165ff5de40eccab0c04c61c8ee5ec13029498f991106dc8b97d012fa1712123a3d93376bf0b73ba949703818143edb86747
6
+ metadata.gz: 54880c5779d9979ac8f97728b5e939fa3af5ffff4e76a5f330314cf3eb9b1fd7d609cd15e2be8ba6273019c5441db8d59788013763f2c4c15758024bb70c4e31
7
+ data.tar.gz: 98ab954df3d7f04be3bd6a8f0662a33f0b88626e5ab06c6b5351d3721a3c7de63350af215da5ead09d6e29c2c61434b2aefe1ff9bc5eb11d2f12de68281da86d
data/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  [![Codeship Status for dchacke/entangled](https://codeship.com/projects/9fe9a790-9df7-0132-5fb8-6e77ea26735b/status?branch=master)](https://codeship.com/projects/64679)
4
4
 
5
- Services like Firebase are great because they provide real time data binding between client and server. But they come at a price: You give up control over your back end. Wouldn't it be great to have real time functionality but still keep your beloved Rails back end? That's where Entangled comes in.
5
+ Real time is important. Users have come to expect real time behavior from every website, because they want to see the latest data without having to reload the page. Real time increases their engagement, provides better context for the data they're seeing, and makes collaboration easier.
6
6
 
7
- Entangled stores and syncs data instantly across every device. It is a layer behind your controllers and models that pushes updates to all connected clients in real time. It is cross-browser compatible and even offers real time validations.
7
+ Entangled stores and syncs data from ActiveRecord instantly across every device. It is a layer behind your models and controllers that pushes updates to all connected clients in real time. It is cross-browser compatible and offers real time validations.
8
8
 
9
- Real time data binding should be the default, not an add-on. Entangled aims at making real time features as easy to implement as possible, while at the same time making your restful controllers thinner. All this without having to give up control over your back end.
9
+ Currently, Entangled runs on Rails 4.2 in the back end and Angular in the front end.
10
10
 
11
11
  ## Installation
12
12
  Add this line to your application's Gemfile:
@@ -130,7 +130,7 @@ end
130
130
 
131
131
  Note the following:
132
132
 
133
- - All methods are wrapped in a new `broadcast` block needed to send messages to connected clients
133
+ - All methods are wrapped in a new `broadcast` block needed to receive and send data to connected clients
134
134
  - The `index` method will expect an instance variable with the same name as your controller in the plural form (e.g. `@messages` in a `MessagesController`)
135
135
  - The `show`, `create` and `update` methods will expect an instance variable with the singular name of your controller (e.g. `@message` in a `MessagesController`)
136
136
  - Data sent to clients arrives as stringified JSON
@@ -152,7 +152,7 @@ If you store your Redis instance in `$redis` or `REDIS` (e.g. in an initializer)
152
152
  Depending on your app's settings, you might have to increase the pool size in your database.yml configuration file, since every new socket will open a new connection to your database.
153
153
 
154
154
  ## The Client
155
- You will need to configure your client to create Websockets and understand incoming requests on those sockets. If you use Angular for your front end, you can use the Angular library from this repository. The use of Angular as counterpart of this gem is highly recommended, since its inherent two way data binding complements the real time functionality of this gem nicely.
155
+ You will need to configure your client to create Websockets and understand incoming requests on those sockets. In order to use the helper methods for the front end provided by the Entangled Angular library, you must use Angular in your front end. The use of Angular as counterpart of this gem is highly recommended, since its inherent two way data binding complements the real time functionality of this gem nicely.
156
156
 
157
157
  ### Installation
158
158
  You can either download or reference the file `entangled.js` from this repository, or simply install it with Bower:
@@ -180,7 +180,7 @@ app.factory('Message', function(Entangled) {
180
180
 
181
181
  In the above example, first we inject Entangled into our service, then instantiate a new Entangled object and return it. The Entangled object takes one argument when instantiated: the URL of your resource's index action (in this case, `/messages`). Note that the socket URL looks just like a standard restful URL with http, except that the protocol part has been switched with `ws` to use the websocket protocol. Also note that you need to use `wss` instead if you want to use SSL.
182
182
 
183
- The Entangled service come with these functions:
183
+ The Entangled service comes with these functions:
184
184
 
185
185
  - `new(params)`
186
186
  - `create(params, callback)`
@@ -245,12 +245,7 @@ $scope.message.$destroy(function() {
245
245
  });
246
246
  ```
247
247
 
248
- All functions above will interact with your server's controllers in real time.
249
-
250
- If data in your server's database changes, so will your scope variables - in real time, for all connected clients.
251
-
252
- ### Available Functions
253
- A number of functions is attached to Entangled JavaScript objects. They basically mimic ActiveRecord's behavior in the back end to make the database more accessible in the front end.
248
+ All functions above will interact with your server's controllers in real time. Your scope variables will always reflect your server's most current data.
254
249
 
255
250
  #### Validations
256
251
  Objects from the Entangled service automatically receive ActiveRecord's error messages from your model when you `$save()`. An additional property called `errors` containing the error messages is available, formatted the same way you're used to from calling `.errors` on a model in Rails.
@@ -291,7 +286,7 @@ $scope.message.$save(function() {
291
286
  Note that `$valid()` and `$invalid()` should only be used after $saving a resource, i.e. in the callback of `$save`, since they don't actually invoke server side validations. They only check if a resource contains errors.
292
287
 
293
288
  #### Persistence
294
- Just like with ActiveRecord's `persisted?` method, you can use `$persisted()` on an object to check if it was successfully stored in the database.
289
+ Just as with ActiveRecord's `persisted?` method, you can use `$persisted()` on an object to check if it was successfully stored in the database.
295
290
 
296
291
  ```javascript
297
292
  $scope.message.$persisted();
@@ -302,16 +297,28 @@ $scope.message.$persisted();
302
297
  This gem is best used for Rails apps that serve as APIs only and are not concerned with rendering views, since Entangled controllers cannot render views. A front end separate from your Rails app is recommended, either in your Rails app's public directory, or a separate front end app altogether.
303
298
 
304
299
  ## Limitations
305
- The gem rely's heavily on convention over configuration and currently only works with restful style controllers as shown above. More customization will be available soon.
300
+ The gem relies heavily on convention over configuration and currently only works with restful style controllers as shown above. More features will be available soon, such as associations, authentication, and more.
301
+
302
+ ## Development Priorities
303
+ The following features are to be implemented next:
304
+
305
+ - Offline capabilities - when client is disconnected, put websocket interactions in a queue and dequeue all once connected again
306
+ - Support for authentication
307
+ - Remove angular dependencies from bower package (they're currently all being downloaded as well when doing bower install)
308
+ - On Heroku (maybe in production in general), objects are always in different order depending on their attributes
309
+ - Add $onChange listener to objects
310
+ - Add diagram on how it works to Readme
311
+ - Reuse open DB connections to reduce pool-size - currently, a new db connection is established for every request, which quickly gets out of hand. Only one DB connection should be opened and maintained per client
312
+ - Check if Rails 4.0.0 supported too
306
313
 
307
314
  ## Contributing
308
315
  1. [Fork it](https://github.com/dchacke/entangled/fork) - you will notice that the repo comes with a back end and a front end part to test both parts of the gem
309
316
  2. Run `$ bundle install` in the root of the repo
310
317
  3. Run `$ bower install` and `$ npm install` in spec/dummy/public
311
- 4. The back end example app resides in spec/dummy; you can run `rails` and `rake` commands in there if you prefix them with `bin/`, i.e. `$ bin/rails s` or `$ bin/rake db:schema:load`; run your tests in the root of the repo by running `$ rspec`
312
- 5. The front end example app resides in spec/dummy/public. To look at it in your browser, cd into spec/dummy/public and run `$ bin/rails s`. Tests for this part of the app can be located under spec/dummy/public/test and are written with Jasmine. To run the tests, first run `$ bin/rails -e test` to start up the server in test mode, and then run `$ grunt test` in a new terminal tab. It's important to remember that changes you make to the server will not take effect until you restart the server since you're running it in the test environment! Also remember to prepare the test database by running `$ bin/rake db:test:prepare`
313
- 6. The Entangled Angular service resides in spec/dummy/public/app/entangled/entangled.js. This is where you can make changes to the service; a copy of it, living in /entangled.js at the root of the repo, should be kept in sync for it to be available with Bower, so it's best if you replace this file with the one from the dummy app should have made any changes to the latter
314
- 7. Write your tests
318
+ 4. The back end example app resides in spec/dummy. You can run `rails` and `rake` commands in there if you prefix them with `bin/`, i.e. `$ bin/rails s` or `$ bin/rake db:schema:load`. Run your Rails tests in the root of the repo by running `$ rspec`
319
+ 5. The front end example app resides in spec/dummy/public. To look at it in your browser, cd into spec/dummy/public and run `$ bin/rails s`. Tests for this part of the app can be located under spec/dummy/public/test and are written with Jasmine. To run the tests, first run `$ bin/rails -e test` to start up the server in test mode, and then run `$ grunt test` in a new terminal tab. It's important to remember that changes you make to the server will not take effect until you restart the server since you're running it in the test environment. Also remember to prepare the test database by running `$ bin/rake db:test:prepare`
320
+ 6. The Entangled Angular service resides in spec/dummy/public/app/entangled/entangled.js. This is where you can make changes to the service. A copy of it, living in /entangled.js at the root of the repo, should be kept in sync for it to be available with Bower. Once you're done editing spec/dummy/public/app/entangled/entangled.js, copy it over to /entangled.js
321
+ 7. Write your tests. Test coverage is required
315
322
  8. Write your feature to make the tests pass
316
323
  9. Stage and commit your changes
317
324
  10. Push to a new feature branch in your repo
data/bower.json CHANGED
@@ -11,7 +11,6 @@
11
11
  "lib",
12
12
  "spec",
13
13
  ".gitignore",
14
- "entangled-0.0.9.gem",
15
14
  "entangled.gemspec",
16
15
  "Gemfile",
17
16
  "Gemfile.lock",
data/entangled.js CHANGED
@@ -1,269 +1 @@
1
- // Register Angular module and call it 'entangled'
2
- angular.module('entangled', [])
3
-
4
- // Register service and call it 'Entangled'
5
- .factory('Entangled', function() {
6
- // Every response coming from the server will be wrapped
7
- // in a Resource constructor to represent a CRUD-able
8
- // resource that can be saved and destroyed using the
9
- // methods $save() and $destroy. A Resource also
10
- // stores the socket's URL it was retrieved from so it
11
- // can be reused for other requests.
12
- var Resource = function(params, webSocketUrl) {
13
- // Assign proerties
14
- for (var key in params) {
15
- // Skip inherent object properties
16
- if (params.hasOwnProperty(key)) {
17
- this[key] = params[key];
18
- }
19
- }
20
-
21
- this.webSocketUrl = webSocketUrl;
22
- };
23
-
24
- // $save() will send a request to the server
25
- // to either create a new record or update
26
- // an existing, depending on whether or not
27
- // an id is present.
28
- Resource.prototype.$save = function(callback) {
29
- var that = this;
30
-
31
- if (this.id) {
32
- // Update
33
- var socket = new WebSocket(that.webSocketUrl + '/' + that.id + '/update');
34
- socket.onopen = function() {
35
- socket.send(JSON.stringify(that));
36
- };
37
-
38
- // Receive updated resource from server
39
- socket.onmessage = function(event) {
40
- if (event.data) {
41
- var data = JSON.parse(event.data);
42
-
43
- // Assign/override new data (such as updated_at, etc)
44
- if (data.resource) {
45
- for (key in data.resource) {
46
- that[key] = data.resource[key];
47
- }
48
- }
49
- }
50
-
51
- // Pass 'that' to callback for create
52
- // function so that the create function
53
- // can pass the created resource to its
54
- // own callback; not needed for $save per se
55
- if (callback) callback(that);
56
- };
57
- } else {
58
- // Create
59
- var socket = new WebSocket(that.webSocketUrl + '/create');
60
-
61
- // Send attributes to server
62
- socket.onopen = function() {
63
- socket.send(JSON.stringify(that));
64
- };
65
-
66
- // Receive saved resource from server
67
- socket.onmessage = function(event) {
68
- if (event.data) {
69
- var data = JSON.parse(event.data);
70
-
71
- // Assign/override new data (such as id, created_at,
72
- // updated_at, etc)
73
- if (data.resource) {
74
- for (key in data.resource) {
75
- that[key] = data.resource[key];
76
- }
77
- }
78
- }
79
-
80
- // Pass 'that' to callback for create
81
- // function so that the create function
82
- // can pass the created resource to its
83
- // own callback; not needed for $save per se
84
- if (callback) callback(that);
85
- };
86
- }
87
- };
88
-
89
- // $update() updates a record in place
90
- Resource.prototype.$update = function(params, callback) {
91
- // Update object in memory
92
- for (var key in params) {
93
- // Skip inherent object properties
94
- if (params.hasOwnProperty(key)) {
95
- this[key] = params[key];
96
- }
97
- }
98
-
99
- // Save object
100
- this.$save(callback);
101
- };
102
-
103
- // $destroy() will send a request to the server to
104
- // destroy an existing record.
105
- Resource.prototype.$destroy = function(callback) {
106
- var socket = new WebSocket(this.webSocketUrl + '/' + this.id + '/destroy');
107
- socket.onopen = function() {
108
- // It's fine to send an empty message since the
109
- // socket's URL contains all the information
110
- // needed to destroy the record (the id).
111
- socket.send(null);
112
-
113
- if (callback) callback();
114
- };
115
- };
116
-
117
- // $valid() checks if any errors are attached to the object
118
- // and return false if so, false otherwise. This doesn't actually
119
- // invoke server side validations, so it should only be used
120
- // after calling $save() to check if the record was successfully
121
- // stored in the database
122
- Resource.prototype.$valid = function() {
123
- return !(this.errors && Object.keys(this.errors).length);
124
- };
125
-
126
- // $invalid() returns the opposite of $valid()
127
- Resource.prototype.$invalid = function() {
128
- return !this.$valid();
129
- };
130
-
131
- // $persisted() checks if the record was successfully stored
132
- // in the back end's database
133
- Resource.prototype.$persisted = function() {
134
- return !!this.id;
135
- };
136
-
137
- // Resources wraps all individual Resource objects
138
- // in a collection.
139
- var Resources = function(resources, webSocketUrl) {
140
- this.all = [];
141
-
142
- for (var i = 0; i < resources.length; i++) {
143
- var resource = new Resource(resources[i], webSocketUrl);
144
- this.all.push(resource);
145
- }
146
- };
147
-
148
- // Entangled is the heart of this service. It contains
149
- // several methods to instantiate a new Resource,
150
- // retrieve an existing Resource from the server,
151
- // and retrieve a collection of existing Resources
152
- // from the server.
153
- //
154
- // Entangled is a constructor that takes the URL
155
- // of the index action on the server where the
156
- // Resources can be retrieved.
157
- var Entangled = function(webSocketUrl) {
158
- // Store the root URL that sockets
159
- // will connect to
160
- this.webSocketUrl = webSocketUrl;
161
- };
162
-
163
- // Function to instantiate a new Resource, optionally
164
- // with given parameters
165
- Entangled.prototype.new = function(params) {
166
- return new Resource(params, this.webSocketUrl);
167
- };
168
-
169
- // Retrieve all Resources from the root of the socket's
170
- // URL
171
- Entangled.prototype.all = function(callback) {
172
- var socket = new WebSocket(this.webSocketUrl);
173
-
174
- socket.onmessage = function(event) {
175
- // If the message from the server isn't empty
176
- if (event.data.length) {
177
- // Convert message to JSON
178
- var data = JSON.parse(event.data);
179
-
180
- // If the collection of Resources was sent
181
- if (data.resources) {
182
- // Store retrieved Resources in property
183
- this.resources = new Resources(data.resources, socket.url);
184
- } else if (data.action) {
185
- if (data.action === 'create') {
186
- // If new Resource was created, add it to the
187
- // collection
188
- this.resources.all.push(new Resource(data.resource, socket.url));
189
- } else if (data.action === 'update') {
190
- // If an existing Resource was updated,
191
- // update it in the collection as well
192
- var index;
193
-
194
- for (var i = 0; i < this.resources.all.length; i++) {
195
- if (this.resources.all[i].id === data.resource.id) {
196
- index = i;
197
- }
198
- }
199
-
200
- this.resources.all[index] = new Resource(data.resource, socket.url);
201
- } else if (data.action === 'destroy') {
202
- // If a Resource was destroyed, remove it
203
- // from Resources as well
204
- var index;
205
-
206
- for (var i = 0; i < this.resources.all.length; i++) {
207
- if (this.resources.all[i].id === data.resource.id) {
208
- index = i;
209
- }
210
- }
211
-
212
- this.resources.all.splice(index, 1);
213
- } else {
214
- console.log('Something else other than CRUD happened...');
215
- console.log(data);
216
- }
217
- }
218
- }
219
-
220
- // Run the callback and pass in the
221
- // resulting collection
222
- callback(this.resources.all);
223
- };
224
- };
225
-
226
- // Instantiate and persist a record in one go
227
- Entangled.prototype.create = function(params, callback) {
228
- var resource = this.new(params);
229
- resource.$save(callback);
230
- };
231
-
232
- // Find an individual Resource on the server
233
- Entangled.prototype.find = function(id, callback) {
234
- var webSocketUrl = this.webSocketUrl;
235
- var socket = new WebSocket(webSocketUrl + '/' + id);
236
-
237
- socket.onmessage = function(event) {
238
- // If the message from the server isn't empty
239
- if (event.data.length) {
240
- // Parse message and convert to JSON
241
- var data = JSON.parse(event.data);
242
-
243
- if (data.resource && !data.action) {
244
- // If the Resource was sent from the server,
245
- // store it
246
- this.resource = new Resource(data.resource, webSocketUrl);
247
- } else if (data.action) {
248
- if (data.action === 'update') {
249
- // If the stored Resource was updated,
250
- // update it here as well
251
- this.resource = new Resource(data.resource, webSocketUrl);
252
- } else if (data.action === 'destroy') {
253
- // If the stored Resource was destroyed,
254
- // remove it from here as well
255
- this.resource = undefined;
256
- }
257
- } else {
258
- console.log('Something else other than CRUD happened...');
259
- console.log(data);
260
- }
261
- }
262
-
263
- // Run callback with retrieved Resource
264
- callback(this.resource);
265
- };
266
- };
267
-
268
- return Entangled;
269
- });
1
+ angular.module("entangled",[]).factory("Entangled",function(){var e=function(e,r){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);this.webSocketUrl=r};e.prototype.$save=function(e){var r=this;if(this.id){var t=new WebSocket(r.webSocketUrl+"/"+r.id+"/update");t.onopen=function(){t.send(JSON.stringify(r))},t.onmessage=function(t){if(t.data){var o=JSON.parse(t.data);if(o.resource)for(key in o.resource)r[key]=o.resource[key]}e&&e(r)}}else{var t=new WebSocket(r.webSocketUrl+"/create");t.onopen=function(){t.send(JSON.stringify(r))},t.onmessage=function(t){if(t.data){var o=JSON.parse(t.data);if(o.resource)for(key in o.resource)r[key]=o.resource[key]}e&&e(r)}}},e.prototype.$update=function(e,r){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);this.$save(r)},e.prototype.$destroy=function(e){var r=new WebSocket(this.webSocketUrl+"/"+this.id+"/destroy");r.onopen=function(){r.send(null),e&&e()}},e.prototype.$valid=function(){return!(this.errors&&Object.keys(this.errors).length)},e.prototype.$invalid=function(){return!this.$valid()},e.prototype.$persisted=function(){return!!this.id};var r=function(r,t){this.all=[];for(var o=0;o<r.length;o++){var s=new e(r[o],t);this.all.push(s)}},t=function(e){this.webSocketUrl=e};return t.prototype["new"]=function(r){return new e(r,this.webSocketUrl)},t.prototype.all=function(t){var o=new WebSocket(this.webSocketUrl);o.onmessage=function(s){if(s.data.length){var n=JSON.parse(s.data);if(n.resources)this.resources=new r(n.resources,o.url);else if(n.action)if("create"===n.action)this.resources.all.push(new e(n.resource,o.url));else if("update"===n.action){for(var i,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===n.resource.id&&(i=a);this.resources.all[i]=new e(n.resource,o.url)}else if("destroy"===n.action){for(var i,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===n.resource.id&&(i=a);this.resources.all.splice(i,1)}else console.log("Something else other than CRUD happened..."),console.log(n)}t(this.resources.all)}},t.prototype.create=function(e,r){var t=this["new"](e);t.$save(r)},t.prototype.find=function(r,t){var o=this.webSocketUrl,s=new WebSocket(o+"/"+r);s.onmessage=function(r){if(r.data.length){var s=JSON.parse(r.data);s.resource&&!s.action?this.resource=new e(s.resource,o):s.action?"update"===s.action?this.resource=new e(s.resource,o):"destroy"===s.action&&(this.resource=void 0):(console.log("Something else other than CRUD happened..."),console.log(s))}t(this.resource)}},t});
@@ -30,13 +30,17 @@ module Entangled
30
30
  # Channel name for collection of resources, used in index
31
31
  # action
32
32
  def collection_channel
33
- resources_name
33
+ model.channel
34
+ end
35
+
36
+ # The model for this controller. E.g. Taco for a TacosController
37
+ def model
38
+ controller_name.classify.constantize
34
39
  end
35
40
 
36
41
  # Channel name for single resource, used in show action
37
42
  def member_channel
38
- instance = member
39
- "#{resources_name}/#{instance.to_param}"
43
+ member.channel
40
44
  end
41
45
 
42
46
  def collection
@@ -57,7 +57,7 @@ module Entangled
57
57
 
58
58
  # The inferred channel name. For example, if the class name
59
59
  # is DeliciousTaco, the inferred channel name is "delicious_tacos"
60
- def inferred_channel_name
60
+ def channel
61
61
  name.underscore.pluralize
62
62
  end
63
63
 
@@ -79,6 +79,15 @@ module Entangled
79
79
  attributes.merge(errors: errors).as_json
80
80
  end
81
81
 
82
+ # The inferred channel name for a single record
83
+ # containing the inferred channel name from the class
84
+ # and the record's id. For example, if it's a
85
+ # DeliciousTaco with the id 1, the inferred channel
86
+ # name for the single record is "delicious_tacos/1"
87
+ def channel
88
+ "#{self.class.channel}/#{self.to_param}"
89
+ end
90
+
82
91
  private
83
92
 
84
93
  # Publishes to client. Whoever is subscribed
@@ -86,25 +95,16 @@ module Entangled
86
95
  # gets the message
87
96
  def publish(action)
88
97
  redis.publish(
89
- self.class.inferred_channel_name,
98
+ self.class.channel,
90
99
  json(action)
91
100
  )
92
101
 
93
102
  redis.publish(
94
- inferred_channel_name_for_single_record,
103
+ channel,
95
104
  json(action)
96
105
  )
97
106
  end
98
107
 
99
- # The inferred channel name for a single record
100
- # containing the inferred channel name from the class
101
- # and the record's id. For example, if it's a
102
- # DeliciousTaco with the id 1, the inferred channel
103
- # name for the single record is "delicious_tacos/1"
104
- def inferred_channel_name_for_single_record
105
- "#{self.class.inferred_channel_name}/#{to_param}"
106
- end
107
-
108
108
  # JSON containing the type of action (:create, :update
109
109
  # or :destroy) and the record itself. This is eventually
110
110
  # broadcast to the client
@@ -1,3 +1,3 @@
1
1
  module Entangled
2
- VERSION = "0.0.17"
2
+ VERSION = "0.0.18"
3
3
  end
@@ -6,9 +6,17 @@ RSpec.describe Message, type: :model do
6
6
  end
7
7
 
8
8
  describe 'Methods' do
9
- describe '.inferred_channel_name' do
9
+ describe '.channel' do
10
10
  it 'is the underscore, pluralized model name' do
11
- expect(Message.inferred_channel_name).to eq 'messages'
11
+ expect(Message.channel).to eq 'messages'
12
+ end
13
+ end
14
+
15
+ describe '#channel' do
16
+ let(:message) { Message.create(body: 'foo') }
17
+
18
+ it "is the class's channel name plus the member as param" do
19
+ expect(message.channel).to eq "messages/#{message.to_param}"
12
20
  end
13
21
  end
14
22
 
@@ -27,7 +35,7 @@ RSpec.describe Message, type: :model do
27
35
  redis = stub_redis
28
36
 
29
37
  expect(redis).to have_received(:publish).with(
30
- 'messages', {
38
+ Message.channel, {
31
39
  action: :create,
32
40
  resource: message
33
41
  }.to_json
@@ -38,7 +46,7 @@ RSpec.describe Message, type: :model do
38
46
  redis = stub_redis
39
47
 
40
48
  expect(redis).to have_received(:publish).with(
41
- "messages/#{message.to_param}", {
49
+ message.channel, {
42
50
  action: :create,
43
51
  resource: message
44
52
  }.to_json
@@ -55,7 +63,7 @@ RSpec.describe Message, type: :model do
55
63
  message.update(body: 'bar')
56
64
 
57
65
  expect(redis).to have_received(:publish).with(
58
- 'messages', {
66
+ Message.channel, {
59
67
  action: :update,
60
68
  resource: message
61
69
  }.to_json
@@ -68,7 +76,7 @@ RSpec.describe Message, type: :model do
68
76
  message.update(body: 'bar')
69
77
 
70
78
  expect(redis).to have_received(:publish).with(
71
- "messages/#{message.to_param}", {
79
+ message.channel, {
72
80
  action: :update,
73
81
  resource: message
74
82
  }.to_json
@@ -85,7 +93,7 @@ RSpec.describe Message, type: :model do
85
93
  message.destroy
86
94
 
87
95
  expect(redis).to have_received(:publish).with(
88
- 'messages', {
96
+ Message.channel, {
89
97
  action: :destroy,
90
98
  resource: message
91
99
  }.to_json
@@ -98,7 +106,7 @@ RSpec.describe Message, type: :model do
98
106
  message.destroy
99
107
 
100
108
  expect(redis).to have_received(:publish).with(
101
- "messages/#{message.to_param}", {
109
+ message.channel, {
102
110
  action: :destroy,
103
111
  resource: message
104
112
  }.to_json
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entangled
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Charles Hackethal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-06 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler