entangled 0.0.15 → 0.0.16

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: 494cf5b44c0dfd9bcab9e70540e048f5673ece7d
4
- data.tar.gz: db4d77e01e589148f03dac03fac802f515bfecfd
3
+ metadata.gz: 9c1338c6837e0167bc7fab4bf7f0ca67a2e572ba
4
+ data.tar.gz: 27dc18b0cb3570ae172c603baca469a8958ead45
5
5
  SHA512:
6
- metadata.gz: 39587a9ec99d12235f0bfc1d32d67a360358183cbecf7d6247a935c02ef6fb46624a7fc221f01d759bc40b383383bf26f2fce6fe38f0e93837afe647c7d7e9f3
7
- data.tar.gz: cb264b51a9afc3de28478ab4ebb3c5c676e49e2126ed8a4c8dbc845dd3c288fdef89b07bb6448c84867bfcaedb43b86453a3ab227b88f0f50856619cfbc9305f
6
+ metadata.gz: 89baa6f21fd914f7e8f6664a5712ac6af91891bb210b28be642c0b5acd36f6bf287e70a7a39888f2cf8e17397ed0bd3d1de06b66ea8bded1982d08946c7273e9
7
+ data.tar.gz: edcafa59d08bfedb94741745f7a6fb8365ff87a68fd8a83ac2409876bdd8601e0fd0bc9a9be40730a1a3ee5f035a173c2fc1d6eb4f8b4ae82e5d919c096d0a38
data/README.md CHANGED
@@ -192,7 +192,7 @@ app.factory('Message', function(Entangled) {
192
192
  });
193
193
  ```
194
194
 
195
- In the above example, first you inject Entangled into your service, then instantiate a new Entangled service passing it the socket to the index action of that resource in your backend (in this case, `/messages`), and then add helper methods to your service.
195
+ In the above example, first we inject Entangled into our service, then instantiate a new Entangled object. The Entangled object takes one argument when instantiated: the URL of your resource's index route (in this case, `/messages`). Then we add helper methods to our service. 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.
196
196
 
197
197
  In your controller, you could then inject that `Message` service and use it like so:
198
198
 
@@ -236,11 +236,16 @@ This gem is best used for Rails apps that serve as APIs only and are not concern
236
236
  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.
237
237
 
238
238
  ## Contributing
239
- 1. Fork it ( https://github.com/dchacke/entangled/fork )
240
- 2. Create your feature branch (`git checkout -b my-new-feature`)
241
- 3. Commit your changes (`git commit -am 'Add some feature'`)
242
- 4. Push to the branch (`git push origin my-new-feature`)
243
- 5. Create a new Pull Request
239
+ 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
240
+ 2. Run `$ bundle install` in the root of the repo
241
+ 3. Run `$ bower install` and `$ npm install` in spec/dummy/public
242
+ 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`
243
+ 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!
244
+ 6. Write your tests
245
+ 7. Write your feature to make the tests pass
246
+ 8. Stage and commit your changes
247
+ 9. Push to a new feature branch in your repo
248
+ 10. Send me a pull request!
244
249
 
245
250
  ## Credits
246
251
  Thanks to [Ilias Tsangaris](https://github.com/iliastsangaris) for inspiring the name "Entanglement" based on [Quantum Entanglement](http://en.wikipedia.org/wiki/Quantum_entanglement) where pairs or groups of particles always react to changes as a whole, i.e. changes to one particle will result in immediate change of all particles in the group.
@@ -144,16 +144,35 @@ module Entangled
144
144
  tubesock.onmessage do |m|
145
145
  params[resource_name.to_sym] = JSON.parse(m)
146
146
  yield
147
+
148
+ # Send resource that was just created back to client. The resource
149
+ # on the client will be overridden with this one. This is important
150
+ # so that the id, created_at and updated_at and possibly other
151
+ # attributes arrive on the client
152
+ if member
153
+ tubesock.send_data({
154
+ resource: member
155
+ }.to_json)
156
+ end
147
157
  end
148
158
 
149
159
  # If the controller's action name is 'update', a record should be
150
160
  # updated. Before yielding, the params hash has to be prepared
151
- # with attributes sent to the socket. The default attributes
152
- # id, created_at, and updated_at should not be included in params.
161
+ # with attributes sent to the socket
153
162
  when 'update'
154
163
  tubesock.onmessage do |m|
155
164
  params[resource_name.to_sym] = JSON.parse(m)
156
165
  yield
166
+
167
+ # Send resource that was just updated back to client. The resource
168
+ # on the client will be overridden with this one. This is important
169
+ # so that the new updated_at and possibly other attributes arrive
170
+ # on the client
171
+ if member
172
+ tubesock.send_data({
173
+ resource: member
174
+ }.to_json)
175
+ end
157
176
  end
158
177
 
159
178
  # For every other controller action, simply wrap whatever is
@@ -70,6 +70,15 @@ module Entangled
70
70
  module InstanceMethods
71
71
  include Entangled::Helpers
72
72
 
73
+ # Override the as_json method so that the
74
+ # JSON representation of the resource includes
75
+ # its errors. This is necessary so that errors
76
+ # are sent back to the client along with the
77
+ # resource on create and update
78
+ def as_json(options = {})
79
+ attributes.merge(errors: errors).as_json
80
+ end
81
+
73
82
  private
74
83
 
75
84
  # Publishes to client. Whoever is subscribed
@@ -1,3 +1,3 @@
1
1
  module Entangled
2
- VERSION = "0.0.15"
2
+ VERSION = "0.0.16"
3
3
  end
@@ -2,7 +2,6 @@
2
2
  # controller with all five actions
3
3
  class MessagesController < ApplicationController
4
4
  include Entangled::Controller
5
- # before_action :destroy_all, only: :create, if: -> { Rails.env.test? }
6
5
 
7
6
  def index
8
7
  broadcast do
@@ -18,13 +17,14 @@ class MessagesController < ApplicationController
18
17
 
19
18
  def create
20
19
  broadcast do
21
- Message.create(message_params)
20
+ @message = Message.create(message_params)
22
21
  end
23
22
  end
24
23
 
25
24
  def update
26
25
  broadcast do
27
- Message.find(params[:id]).update(message_params)
26
+ @message = Message.find(params[:id])
27
+ @message.update(message_params)
28
28
  end
29
29
  end
30
30
 
@@ -38,9 +38,4 @@ private
38
38
  def message_params
39
39
  params.require(:message).permit(:body)
40
40
  end
41
-
42
- # For test purposes
43
- def destroy_all
44
- Message.destroy_all
45
- end
46
41
  end
@@ -1,4 +1,6 @@
1
1
  class Message < ActiveRecord::Base
2
2
  include Entangled::Model
3
3
  entangle
4
+
5
+ validates :body, presence: true
4
6
  end
@@ -51,7 +51,11 @@ Rails.application.configure do
51
51
  Message.destroy_all
52
52
 
53
53
  # Create one dummy message that the JS tests depend on
54
- Message.create body: 'foo'
54
+ Message.create! body: 'foo'
55
55
  end
56
56
  end
57
+
58
+ # Configure log because the server won't log anything otherwise
59
+ # config.logger = Logger.new(STDOUT)
60
+ # config.logger.level = Logger::ERROR
57
61
  end
@@ -36,15 +36,45 @@ angular.module('entangled', [])
36
36
 
37
37
  if (callback) callback();
38
38
  };
39
+
40
+ // Receive updated resource from server
41
+ socket.onmessage = function(event) {
42
+ if (event.data) {
43
+ var data = JSON.parse(event.data);
44
+
45
+ // Assign/override new data (such as updated_at, etc)
46
+ if (data.resource) {
47
+ for (key in data.resource) {
48
+ that[key] = data.resource[key];
49
+ }
50
+ }
51
+ }
52
+ };
39
53
  } else {
40
54
  // Create
41
55
  var socket = new WebSocket(that.webSocketUrl + '/create');
42
56
 
57
+ // Send attributes to server
43
58
  socket.onopen = function() {
44
59
  socket.send(JSON.stringify(that));
45
60
 
46
61
  if (callback) callback();
47
62
  };
63
+
64
+ // Receive saved resource from server
65
+ socket.onmessage = function(event) {
66
+ if (event.data) {
67
+ var data = JSON.parse(event.data);
68
+
69
+ // Assign/override new data (such as id, created_at,
70
+ // updated_at, etc)
71
+ if (data.resource) {
72
+ for (key in data.resource) {
73
+ that[key] = data.resource[key];
74
+ }
75
+ }
76
+ }
77
+ };
48
78
  }
49
79
  };
50
80
 
@@ -49,10 +49,26 @@ describe('MessagesCtrl', function () {
49
49
  setTimeout(function() {
50
50
  var oldLength = scope.messages.length;
51
51
 
52
+ // Assert it's a new message
53
+ expect(scope.message.id).not.toBeDefined();
54
+
55
+ // Be sure to pass validations in the back end
56
+ scope.message.body = 'foo';
57
+
58
+ // Save it
52
59
  scope.message.$save(function() {
53
60
  setTimeout(function() {
61
+ // Make sure that the message was added to the collection
54
62
  expect(scope.messages.length).toBe(oldLength + 1);
55
- done();
63
+
64
+ // Make sure that it has been persisted and new attributes
65
+ // were sent over from the back end and updated here
66
+ setTimeout(function() {
67
+ expect(scope.message.id).toBeDefined();
68
+ expect(scope.message.created_at).toBeDefined();
69
+ expect(scope.message.updated_at).toBeDefined();
70
+ done();
71
+ }, 100);
56
72
  }, 100);
57
73
  });
58
74
  }, 100);
@@ -66,12 +82,49 @@ describe('MessagesCtrl', function () {
66
82
  // Assert that message has been persisted before
67
83
  expect(message.id).toBeDefined();
68
84
 
85
+ // Remember old updated_at
86
+ var oldUpdatedAt = message.updated_at;
87
+
69
88
  // Update it
70
89
  message.body = 'new body';
71
90
  message.$save(function() {
72
91
  setTimeout(function() {
73
92
  // Assert that message was updated across collection
74
- expect(scope.messages[0].body).toEqual('new body');
93
+ expect(scope.messages[0].body).toBe('new body');
94
+
95
+ // Assert that message was actually updated in back end
96
+ // and attributes have been updated here
97
+ expect(scope.message.updated_at).not.toBe(oldUpdatedAt);
98
+ done();
99
+ }, 100);
100
+ });
101
+ }, 100);
102
+ });
103
+
104
+ it('gets validation errors', function(done) {
105
+ setTimeout(function() {
106
+ // Pick first message
107
+ var message = scope.messages[0];
108
+
109
+ // Assert that message has been persisted before
110
+ expect(message.id).toBeDefined();
111
+
112
+ // Update it so it won't pass validations in the back end
113
+ message.body = '';
114
+
115
+ // Remember old updated_at
116
+ var oldUpdatedAt = message.updated_at;
117
+
118
+ // Save it
119
+ message.$save(function() {
120
+ setTimeout(function() {
121
+ // Assert that message was not updated on server
122
+ expect(message.updated_at).toBe(oldUpdatedAt);
123
+
124
+ // Assert that the message has error messages attached
125
+ // to it
126
+ expect(message.errors.body).toEqual(["can't be blank"])
127
+
75
128
  done();
76
129
  }, 100);
77
130
  });
@@ -106,5 +106,19 @@ RSpec.describe Message, type: :model do
106
106
  end
107
107
  end
108
108
  end
109
+
110
+ describe '#as_json' do
111
+ it 'includes errors' do
112
+ message = Message.create
113
+ expect(message.as_json["errors"][:body]).to include "can't be blank"
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'Validations' do
119
+ it 'validates presence of the body' do
120
+ message = Message.create
121
+ expect(message.errors[:body]).to include "can't be blank"
122
+ end
109
123
  end
110
124
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entangled
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Charles Hackethal
@@ -9831,6 +9831,7 @@ files:
9831
9831
  - spec/dummy/public/test/controllers/messages_test.js
9832
9832
  - spec/dummy/public/views/messages/index.html
9833
9833
  - spec/dummy/public/views/messages/show.html
9834
+ - spec/dummy/tmp/pids/server.pid
9834
9835
  - spec/models/inclusion_exclusion_spec.rb
9835
9836
  - spec/models/message_spec.rb
9836
9837
  - spec/routing/inclusion_exclusion_routing_spec.rb
@@ -19516,6 +19517,7 @@ test_files:
19516
19517
  - spec/dummy/public/views/messages/show.html
19517
19518
  - spec/dummy/Rakefile
19518
19519
  - spec/dummy/README.rdoc
19520
+ - spec/dummy/tmp/pids/server.pid
19519
19521
  - spec/models/inclusion_exclusion_spec.rb
19520
19522
  - spec/models/message_spec.rb
19521
19523
  - spec/routing/inclusion_exclusion_routing_spec.rb