entangled 0.0.23 → 0.0.24

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: d7c388678aa588a1f547b713feb70dbd9f5aaa44
4
- data.tar.gz: 5c4baa78c2e13abb9fdce0aabbd132698a474af4
3
+ metadata.gz: 1a88ff7623ddae9fbcfe0b93bc7080f309a48bf5
4
+ data.tar.gz: 179aa9cd196ea36f70ba8f4baf3d2d6cfc0c5dfe
5
5
  SHA512:
6
- metadata.gz: a740b57b3679899c1c3bde3d2b969f00a5457f826af461626119fdb4083a08eba5c5115b433fc8c243736a00a6c7c074fa9b8c8673c561fd2cf6c18cef72c134
7
- data.tar.gz: 17eb36090addf15cc12ea4a9c346dcb70411ac7273ce613ebfcf08143f9d47c15d0ee02ee8c1185a5b3200febabc2bb8fb13ac17538d205bb4a0b06daa0645e3
6
+ metadata.gz: 26935b60d39af34abfb60595102825d41a85188373bee4c5ac24b04392ceeb5ff8571f35229ef6ecb5432fca0626ac17286534256c3f4e9c9e5216cf4ad092e1
7
+ data.tar.gz: 2440601fc453c11adebee76f0c1bc061bfe74ad4d0c0b996d93b01f433e120d66bf916e528f447b54fd48d9da7e420bca46352a8f540bc4c15d9dc524b8477d4
data/README.md CHANGED
@@ -413,7 +413,8 @@ The gem relies heavily on convention over configuration and currently only works
413
413
  ## Development Priorities
414
414
  The following features are to be implemented next:
415
415
 
416
- - Support more than one `belongs_to` association in back end
416
+ - Check if routes really allow options right now. For example, what if I pass in shallow: true? Run rake routes to check!
417
+ - Allow for more than one level of nesting of `#channels` in `Entangled::Model`
417
418
  - Support `belongsTo` in front end
418
419
  - Support deeply nested `belongs_to`, e.g. `Parent > Child > Grandchild`
419
420
  - Support `has_one` association in back end and front end
@@ -430,6 +431,7 @@ The following features are to be implemented next:
430
431
  - Freeze destroyed object
431
432
  - Set `$persisted()` to false on a destroyed object
432
433
  - Add `.destroyAll()` function to `Resources`
434
+ - Add support for plain JavaScript usage (without Angular) and add section about that to Readme
433
435
 
434
436
  ## Contributing
435
437
  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
@@ -73,59 +73,54 @@ module Entangled
73
73
  attributes.merge(errors: errors).as_json
74
74
  end
75
75
 
76
- # The channel name for a single record containing the
77
- # inferred channel name from the class and the record's
78
- # id. For example, if it's a DeliciousTaco with the id 1,
79
- # the member channel for the single record is "delicious_tacos/1".
80
- # Nesting is automatically applied through the use of
81
- # the collection channel.
76
+ # Build channels. Channels always at least include
77
+ # a collection channel, i.e. /tacos, and a member
78
+ # channel, i.e. /tacos/1, for direct access.
82
79
  #
83
- # The member channel has to be the same as the path to
84
- # the resource's show action, including a leading
85
- # forward slash
86
- def member_channel
87
- "#{collection_channel}/#{self.to_param}"
88
- end
80
+ # If the model belongs_to other models, two nested
81
+ # channels are added for each belongs_to association.
82
+ # E.g., if child belongs_to parent, the two channels
83
+ # that are added are parents/1/children, and
84
+ # parents/1/children/1, leaving a total of four channels
85
+ def channels
86
+ channels = []
87
+ plural_name = self.class.name.underscore.pluralize
89
88
 
90
- # The inferred channel name for the collection. For example,
91
- # if the class name is DeliciousTaco, the collection channel
92
- # is "delicious_tacos".
93
- #
94
- # If the model belongs to another model, the channel is nested
95
- # accordingly. For example, if a child belongs to a parent,
96
- # the child's collection channel is "parents/1/children".
97
- #
98
- # The collection channel has to be the same as the path to
99
- # the resource's index action, including a leading forward slash
100
- def collection_channel
101
- belongs_to_assocations = self.class.reflect_on_all_associations(:belongs_to)
102
- own_channel = self.class.name.underscore.pluralize
103
-
104
- if belongs_to_assocations.any?
105
- parent = send(belongs_to_assocations.first.name)
106
- "#{parent.member_channel}/#{own_channel}"
107
- else
108
- "/#{own_channel}"
89
+ # Add collection's channel
90
+ channels << "/#{plural_name}"
91
+
92
+ # Add member's channel
93
+ channels << "/#{plural_name}/#{to_param}"
94
+
95
+ # Find parent names from belongs_to associations
96
+ parents = self.class.reflect_on_all_associations(:belongs_to)
97
+
98
+ # Add nested channels for each parent
99
+ parents.map(&:name).each do |parent_name|
100
+ # Get parent record from name
101
+ parent = send(parent_name)
102
+
103
+ # Get parent class's plural underscore name
104
+ parent_plural_name = parent_name.to_s.underscore.pluralize
105
+
106
+ # Add collection's channel nested under parent's member channel
107
+ channels << "/#{parent_plural_name}/#{parent.to_param}/#{plural_name}"
108
+
109
+ # Add member's channel nested under parent's member channel
110
+ channels << "/#{parent_plural_name}/#{parent.to_param}/#{plural_name}/#{to_param}"
109
111
  end
112
+
113
+ channels
110
114
  end
111
115
 
112
116
  private
113
117
 
114
118
  # Publishes to client. Whoever is subscribed
115
- # to the model's channel or the record's channel
116
- # gets the message
119
+ # to the model's channels gets the message
117
120
  def publish(action)
118
- # Publish to model's channel
119
- redis.publish(
120
- collection_channel,
121
- json(action)
122
- )
123
-
124
- # Publish to record#s channel
125
- redis.publish(
126
- member_channel,
127
- json(action)
128
- )
121
+ channels.each do |channel|
122
+ redis.publish(channel, json(action))
123
+ end
129
124
  end
130
125
 
131
126
  # JSON containing the type of action (:create, :update
@@ -1,3 +1,3 @@
1
1
  module Entangled
2
- VERSION = "0.0.23"
2
+ VERSION = "0.0.24"
3
3
  end
@@ -14,21 +14,15 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
14
14
  it 'publishes creation' do
15
15
  redis = stub_redis
16
16
 
17
- # Publishing to collection channel
18
- expect(redis).to have_received(:publish).with(
19
- foo.collection_channel, {
20
- action: :create,
21
- resource: foo
22
- }.to_json
23
- )
24
-
25
- # Publishing to member channel
26
- expect(redis).to have_received(:publish).with(
27
- foo.member_channel, {
28
- action: :create,
29
- resource: foo
30
- }.to_json
31
- )
17
+ # Publishing to channels
18
+ foo.channels.each do |channel|
19
+ expect(redis).to have_received(:publish).with(
20
+ channel, {
21
+ action: :create,
22
+ resource: foo
23
+ }.to_json
24
+ )
25
+ end
32
26
  end
33
27
 
34
28
  it 'does not publish update' do
@@ -36,19 +30,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
36
30
 
37
31
  foo.update(body: 'bar')
38
32
 
39
- expect(redis).to have_received(:publish).with(
40
- 'foos', {
41
- action: :update,
42
- resource: foo
43
- }.to_json
44
- ).never
45
-
46
- expect(redis).to have_received(:publish).with(
47
- foo.member_channel, {
48
- action: :update,
49
- resource: foo
50
- }.to_json
51
- ).never
33
+ foo.channels.each do |channel|
34
+ expect(redis).to have_received(:publish).with(
35
+ channel, {
36
+ action: :update,
37
+ resource: foo
38
+ }.to_json
39
+ ).never
40
+ end
52
41
  end
53
42
 
54
43
  it 'does not publish destruction' do
@@ -56,19 +45,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
56
45
 
57
46
  foo.destroy
58
47
 
59
- expect(redis).to have_received(:publish).with(
60
- 'foos', {
61
- action: :destroy,
62
- resource: foo
63
- }.to_json
64
- ).never
65
-
66
- expect(redis).to have_received(:publish).with(
67
- foo.member_channel, {
68
- action: :destroy,
69
- resource: foo
70
- }.to_json
71
- ).never
48
+ foo.channels.each do |channel|
49
+ expect(redis).to have_received(:publish).with(
50
+ channel, {
51
+ action: :destroy,
52
+ resource: foo
53
+ }.to_json
54
+ ).never
55
+ end
72
56
  end
73
57
  end
74
58
 
@@ -79,20 +63,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
79
63
  redis = stub_redis
80
64
 
81
65
  # Publishing to collection channel
82
- expect(redis).to have_received(:publish).with(
83
- bar.collection_channel, {
84
- action: :create,
85
- resource: bar
86
- }.to_json
87
- )
88
-
89
- # Publishing to member channel
90
- expect(redis).to have_received(:publish).with(
91
- bar.member_channel, {
92
- action: :create,
93
- resource: bar
94
- }.to_json
95
- )
66
+ bar.channels.each do |channel|
67
+ expect(redis).to have_received(:publish).with(
68
+ channel, {
69
+ action: :create,
70
+ resource: bar
71
+ }.to_json
72
+ )
73
+ end
96
74
  end
97
75
 
98
76
  it 'publishes the update' do
@@ -100,19 +78,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
100
78
 
101
79
  bar.update(body: 'bar')
102
80
 
103
- expect(redis).to have_received(:publish).with(
104
- bar.collection_channel, {
105
- action: :update,
106
- resource: bar
107
- }.to_json
108
- )
109
-
110
- expect(redis).to have_received(:publish).with(
111
- bar.member_channel, {
112
- action: :update,
113
- resource: bar
114
- }.to_json
115
- )
81
+ bar.channels.each do |channel|
82
+ expect(redis).to have_received(:publish).with(
83
+ channel, {
84
+ action: :update,
85
+ resource: bar
86
+ }.to_json
87
+ )
88
+ end
116
89
  end
117
90
 
118
91
  it 'does not publish destruction' do
@@ -120,19 +93,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
120
93
 
121
94
  bar.destroy
122
95
 
123
- expect(redis).to have_received(:publish).with(
124
- bar.collection_channel, {
125
- action: :destroy,
126
- resource: bar
127
- }.to_json
128
- ).never
129
-
130
- expect(redis).to have_received(:publish).with(
131
- bar.member_channel, {
132
- action: :destroy,
133
- resource: bar
134
- }.to_json
135
- ).never
96
+ bar.channels.each do |channel|
97
+ expect(redis).to have_received(:publish).with(
98
+ channel, {
99
+ action: :destroy,
100
+ resource: bar
101
+ }.to_json
102
+ ).never
103
+ end
136
104
  end
137
105
  end
138
106
 
@@ -142,21 +110,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
142
110
  it 'does not publish the creation' do
143
111
  redis = stub_redis
144
112
 
145
- # Publishing to collection channel
146
- expect(redis).to have_received(:publish).with(
147
- foobar.collection_channel, {
148
- action: :create,
149
- resource: foobar
150
- }.to_json
151
- ).never
152
-
153
- # Publishing to member channel
154
- expect(redis).to have_received(:publish).with(
155
- foobar.member_channel, {
156
- action: :create,
157
- resource: foobar
158
- }.to_json
159
- ).never
113
+ foobar.channels.each do |channel|
114
+ expect(redis).to have_received(:publish).with(
115
+ channel, {
116
+ action: :create,
117
+ resource: foobar
118
+ }.to_json
119
+ ).never
120
+ end
160
121
  end
161
122
 
162
123
  it 'publishes the update' do
@@ -164,19 +125,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
164
125
 
165
126
  foobar.update(body: 'foobar')
166
127
 
167
- expect(redis).to have_received(:publish).with(
168
- foobar.collection_channel, {
169
- action: :update,
170
- resource: foobar
171
- }.to_json
172
- )
173
-
174
- expect(redis).to have_received(:publish).with(
175
- foobar.member_channel, {
176
- action: :update,
177
- resource: foobar
178
- }.to_json
179
- )
128
+ foobar.channels.each do |channel|
129
+ expect(redis).to have_received(:publish).with(
130
+ channel, {
131
+ action: :update,
132
+ resource: foobar
133
+ }.to_json
134
+ )
135
+ end
180
136
  end
181
137
 
182
138
  it 'publishes the destruction' do
@@ -184,19 +140,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
184
140
 
185
141
  foobar.destroy
186
142
 
187
- expect(redis).to have_received(:publish).with(
188
- foobar.collection_channel, {
189
- action: :destroy,
190
- resource: foobar
191
- }.to_json
192
- )
193
-
194
- expect(redis).to have_received(:publish).with(
195
- foobar.member_channel, {
196
- action: :destroy,
197
- resource: foobar
198
- }.to_json
199
- )
143
+ foobar.channels.each do |channel|
144
+ expect(redis).to have_received(:publish).with(
145
+ channel, {
146
+ action: :destroy,
147
+ resource: foobar
148
+ }.to_json
149
+ )
150
+ end
200
151
  end
201
152
  end
202
153
 
@@ -206,21 +157,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
206
157
  it 'publishes the creation' do
207
158
  redis = stub_redis
208
159
 
209
- # Publishing to collection channel
210
- expect(redis).to have_received(:publish).with(
211
- barfoo.collection_channel, {
212
- action: :create,
213
- resource: barfoo
214
- }.to_json
215
- )
216
-
217
- # Publishing to member channel
218
- expect(redis).to have_received(:publish).with(
219
- barfoo.member_channel, {
220
- action: :create,
221
- resource: barfoo
222
- }.to_json
223
- )
160
+ barfoo.channels.each do |channel|
161
+ expect(redis).to have_received(:publish).with(
162
+ channel, {
163
+ action: :create,
164
+ resource: barfoo
165
+ }.to_json
166
+ )
167
+ end
224
168
  end
225
169
 
226
170
  it 'dpes not publish the update' do
@@ -228,19 +172,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
228
172
 
229
173
  barfoo.update(body: 'barfoo')
230
174
 
231
- expect(redis).to have_received(:publish).with(
232
- barfoo.collection_channel, {
233
- action: :update,
234
- resource: barfoo
235
- }.to_json
236
- ).never
237
-
238
- expect(redis).to have_received(:publish).with(
239
- barfoo.member_channel, {
240
- action: :update,
241
- resource: barfoo
242
- }.to_json
243
- ).never
175
+ barfoo.channels.each do |channel|
176
+ expect(redis).to have_received(:publish).with(
177
+ channel, {
178
+ action: :update,
179
+ resource: barfoo
180
+ }.to_json
181
+ ).never
182
+ end
244
183
  end
245
184
 
246
185
  it 'does not publish the destruction' do
@@ -248,19 +187,14 @@ RSpec.describe 'Inclusion/exclusion', type: :model do
248
187
 
249
188
  barfoo.destroy
250
189
 
251
- expect(redis).to have_received(:publish).with(
252
- barfoo.collection_channel, {
253
- action: :destroy,
254
- resource: barfoo
255
- }.to_json
256
- ).never
257
-
258
- expect(redis).to have_received(:publish).with(
259
- barfoo.member_channel, {
260
- action: :destroy,
261
- resource: barfoo
262
- }.to_json
263
- ).never
190
+ barfoo.channels.each do |channel|
191
+ expect(redis).to have_received(:publish).with(
192
+ channel, {
193
+ action: :destroy,
194
+ resource: barfoo
195
+ }.to_json
196
+ ).never
197
+ end
264
198
  end
265
199
  end
266
200
  end
@@ -21,15 +21,25 @@ RSpec.describe Item, type: :model do
21
21
  let(:list) { List.create(name: 'foo') }
22
22
  let(:item) { list.items.create(name: 'bar') }
23
23
 
24
- describe '#member_channel' do
25
- it 'has a nested member channel' do
26
- expect(item.member_channel).to eq "/lists/#{list.to_param}/items/#{item.to_param}"
24
+ describe '#channels' do
25
+ it 'is an array of channels' do
26
+ expect(item.channels).to be_an Array
27
+ end
28
+
29
+ it "includes the collection's channel" do
30
+ expect(item.channels).to include '/items'
31
+ end
32
+
33
+ it "includes the item's direct channel" do
34
+ expect(item.channels).to include "/items/#{item.to_param}"
35
+ end
36
+
37
+ it "includes the collection's nested channel" do
38
+ expect(item.channels).to include "/lists/#{list.to_param}/items"
27
39
  end
28
- end
29
40
 
30
- describe '#collection_channel' do
31
- it 'has a nested collection channel' do
32
- expect(item.collection_channel).to eq "/lists/#{list.to_param}/items"
41
+ it "includes the item's nested channel" do
42
+ expect(item.channels).to include "/lists/#{list.to_param}/items/#{item.to_param}"
33
43
  end
34
44
  end
35
45
  end
@@ -16,15 +16,17 @@ RSpec.describe List, type: :model do
16
16
  describe 'Methods' do
17
17
  let(:list) { List.create(name: 'foo') }
18
18
 
19
- describe '#member_channel' do
20
- it 'has the right channel' do
21
- expect(list.member_channel).to eq "/lists/#{list.to_param}"
19
+ describe '#channels' do
20
+ it 'is an array of channels' do
21
+ expect(list.channels).to be_an Array
22
+ end
23
+
24
+ it "includes the collection's channel" do
25
+ expect(list.channels).to include '/lists'
22
26
  end
23
- end
24
27
 
25
- describe '#collection_channel' do
26
- it 'has the right channel' do
27
- expect(list.collection_channel).to eq '/lists'
28
+ it "includes the member's channel" do
29
+ expect(list.channels).to include "/lists/#{list.to_param}"
28
30
  end
29
31
  end
30
32
  end
@@ -43,23 +45,27 @@ RSpec.describe List, type: :model do
43
45
  it 'broadcasts the creation to the collection channel' do
44
46
  redis = stub_redis
45
47
 
46
- expect(redis).to have_received(:publish).with(
47
- list.collection_channel, {
48
- action: :create,
49
- resource: list
50
- }.to_json
51
- )
48
+ list.channels.each do |channel|
49
+ expect(redis).to have_received(:publish).with(
50
+ channel, {
51
+ action: :create,
52
+ resource: list
53
+ }.to_json
54
+ )
55
+ end
52
56
  end
53
57
 
54
58
  it 'broadcasts the creation to the member channel' do
55
59
  redis = stub_redis
56
60
 
57
- expect(redis).to have_received(:publish).with(
58
- list.member_channel, {
59
- action: :create,
60
- resource: list
61
- }.to_json
62
- )
61
+ list.channels.each do |channel|
62
+ expect(redis).to have_received(:publish).with(
63
+ channel, {
64
+ action: :create,
65
+ resource: list
66
+ }.to_json
67
+ )
68
+ end
63
69
  end
64
70
  end
65
71
 
@@ -71,12 +77,14 @@ RSpec.describe List, type: :model do
71
77
 
72
78
  list.update(name: 'bar')
73
79
 
74
- expect(redis).to have_received(:publish).with(
75
- list.collection_channel, {
76
- action: :update,
77
- resource: list
78
- }.to_json
79
- )
80
+ list.channels.each do |channel|
81
+ expect(redis).to have_received(:publish).with(
82
+ channel, {
83
+ action: :update,
84
+ resource: list
85
+ }.to_json
86
+ )
87
+ end
80
88
  end
81
89
 
82
90
  it 'broadcasts the update to the member channel' do
@@ -84,12 +92,14 @@ RSpec.describe List, type: :model do
84
92
 
85
93
  list.update(name: 'bar')
86
94
 
87
- expect(redis).to have_received(:publish).with(
88
- list.member_channel, {
89
- action: :update,
90
- resource: list
91
- }.to_json
92
- )
95
+ list.channels.each do |channel|
96
+ expect(redis).to have_received(:publish).with(
97
+ channel, {
98
+ action: :update,
99
+ resource: list
100
+ }.to_json
101
+ )
102
+ end
93
103
  end
94
104
  end
95
105
 
@@ -101,12 +111,14 @@ RSpec.describe List, type: :model do
101
111
 
102
112
  list.destroy
103
113
 
104
- expect(redis).to have_received(:publish).with(
105
- list.collection_channel, {
106
- action: :destroy,
107
- resource: list
108
- }.to_json
109
- )
114
+ list.channels.each do |channel|
115
+ expect(redis).to have_received(:publish).with(
116
+ channel, {
117
+ action: :destroy,
118
+ resource: list
119
+ }.to_json
120
+ )
121
+ end
110
122
  end
111
123
 
112
124
  it 'broadcasts the destruction to the member channel' do
@@ -114,12 +126,14 @@ RSpec.describe List, type: :model do
114
126
 
115
127
  list.destroy
116
128
 
117
- expect(redis).to have_received(:publish).with(
118
- list.member_channel, {
119
- action: :destroy,
120
- resource: list
121
- }.to_json
122
- )
129
+ list.channels.each do |channel|
130
+ expect(redis).to have_received(:publish).with(
131
+ channel, {
132
+ action: :destroy,
133
+ resource: list
134
+ }.to_json
135
+ )
136
+ end
123
137
  end
124
138
  end
125
139
  end
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.23
4
+ version: 0.0.24
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-16 00:00:00.000000000 Z
11
+ date: 2015-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler